658 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			658 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include "inc.h"
 | 
						|
#include "store.h"
 | 
						|
 | 
						|
/* Allocate space for the data store. */
 | 
						|
static struct data_store ds_store[NR_DS_KEYS];
 | 
						|
static struct subscription ds_subs[NR_DS_SUBS];
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *			      alloc_data_slot				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static struct data_store *alloc_data_slot(void)
 | 
						|
{
 | 
						|
/* Allocate a new data slot. */
 | 
						|
  int i;
 | 
						|
 | 
						|
  for (i = 0; i < NR_DS_KEYS; i++) {
 | 
						|
	if (!(ds_store[i].flags & DSF_IN_USE))
 | 
						|
		return &ds_store[i];
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				alloc_sub_slot				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static struct subscription *alloc_sub_slot(void)
 | 
						|
{
 | 
						|
/* Allocate a new subscription slot. */
 | 
						|
  int i;
 | 
						|
 | 
						|
  for (i = 0; i < NR_DS_SUBS; i++) {
 | 
						|
	if (!(ds_subs[i].flags & DSF_IN_USE))
 | 
						|
		return &ds_subs[i];
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				lookup_entry				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static struct data_store *lookup_entry(const char *key_name, int type)
 | 
						|
{
 | 
						|
/* Lookup an existing entry by key and type. */
 | 
						|
  int i;
 | 
						|
 | 
						|
  for (i = 0; i < NR_DS_KEYS; i++) {
 | 
						|
	if ((ds_store[i].flags & DSF_IN_USE) /* used */
 | 
						|
		&& (ds_store[i].flags & type) /* same type*/
 | 
						|
		&& !strcmp(ds_store[i].key, key_name)) /* same key*/
 | 
						|
		return &ds_store[i];
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *			     lookup_label_entry				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static struct data_store *lookup_label_entry(unsigned num)
 | 
						|
{
 | 
						|
/* Lookup an existing label entry by num. */
 | 
						|
  int i;
 | 
						|
 | 
						|
  for (i = 0; i < NR_DS_KEYS; i++) {
 | 
						|
	if ((ds_store[i].flags & DSF_IN_USE)
 | 
						|
		&& (ds_store[i].flags & DSF_TYPE_LABEL)
 | 
						|
		&& (ds_store[i].u.u32 == num))
 | 
						|
		return &ds_store[i];
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *			      lookup_sub				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static struct subscription *lookup_sub(const char *owner)
 | 
						|
{
 | 
						|
/* Lookup an existing subscription given its owner. */
 | 
						|
  int i;
 | 
						|
 | 
						|
  for (i = 0; i < NR_DS_SUBS; i++) {
 | 
						|
	if ((ds_subs[i].flags & DSF_IN_USE) /* used */
 | 
						|
		&& !strcmp(ds_subs[i].owner, owner)) /* same key*/
 | 
						|
		return &ds_subs[i];
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				ds_getprocname				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static char *ds_getprocname(endpoint_t e)
 | 
						|
{
 | 
						|
/* Get a process name given its endpoint. */
 | 
						|
	struct data_store *dsp;
 | 
						|
 | 
						|
	static char *first_proc_name = "ds";
 | 
						|
	endpoint_t first_proc_ep = DS_PROC_NR;
 | 
						|
 | 
						|
	if(e == first_proc_ep)
 | 
						|
		return first_proc_name;
 | 
						|
 | 
						|
	if((dsp = lookup_label_entry(e)) != NULL)
 | 
						|
		return dsp->key;
 | 
						|
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				ds_getprocep				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static endpoint_t ds_getprocep(const char *s)
 | 
						|
{
 | 
						|
/* Get a process endpoint given its name. */
 | 
						|
	struct data_store *dsp;
 | 
						|
 | 
						|
	if((dsp = lookup_entry(s, DSF_TYPE_LABEL)) != NULL)
 | 
						|
		return dsp->u.u32;
 | 
						|
	panic("ds_getprocep: process endpoint not found");
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				 check_auth				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static int check_auth(const struct data_store *p, endpoint_t ep, int perm)
 | 
						|
{
 | 
						|
/* Check authorization for a given type of permission. */
 | 
						|
	char *source;
 | 
						|
 | 
						|
	if(!(p->flags & perm))
 | 
						|
		return 1;
 | 
						|
 | 
						|
	source = ds_getprocname(ep);
 | 
						|
	return source && !strcmp(p->owner, source);
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				get_key_name				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static int get_key_name(const message *m_ptr, char *key_name)
 | 
						|
{
 | 
						|
/* Get key name given an input message. */
 | 
						|
  int r;
 | 
						|
 | 
						|
  if (m_ptr->DS_KEY_LEN > DS_MAX_KEYLEN || m_ptr->DS_KEY_LEN < 2) {
 | 
						|
	printf("DS: bogus key length (%d) from %d\n", m_ptr->DS_KEY_LEN,
 | 
						|
		m_ptr->m_source);
 | 
						|
	return EINVAL;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Copy name from caller. */
 | 
						|
  r = sys_safecopyfrom(m_ptr->m_source,
 | 
						|
	(cp_grant_id_t) m_ptr->DS_KEY_GRANT, 0, 
 | 
						|
	(vir_bytes) key_name, m_ptr->DS_KEY_LEN);
 | 
						|
  if(r != OK) {
 | 
						|
	printf("DS: publish: copy failed from %d: %d\n", m_ptr->m_source, r);
 | 
						|
	return r;
 | 
						|
  }
 | 
						|
 | 
						|
  key_name[DS_MAX_KEYLEN-1] = '\0';
 | 
						|
 | 
						|
  return OK;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				check_sub_match				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static int check_sub_match(const struct subscription *subp,
 | 
						|
		struct data_store *dsp, endpoint_t ep)
 | 
						|
{
 | 
						|
/* Check if an entry matches a subscription. Return 1 in case of match. */
 | 
						|
  return (check_auth(dsp, ep, DSF_PRIV_SUBSCRIBE)
 | 
						|
	  && regexec(&subp->regex, dsp->key, 0, NULL, 0) == 0)
 | 
						|
	  ? 1 : 0;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *			     update_subscribers				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static void update_subscribers(struct data_store *dsp, int set)
 | 
						|
{
 | 
						|
/* If set = 1, set bit in the sub bitmap of any subscription matching the given
 | 
						|
 * entry, otherwise clear it. In both cases, notify the subscriber.
 | 
						|
 */
 | 
						|
	int i;
 | 
						|
	int nr = dsp - ds_store;
 | 
						|
	endpoint_t ep;
 | 
						|
 | 
						|
	for(i = 0; i < NR_DS_SUBS; i++) {
 | 
						|
		if(!(ds_subs[i].flags & DSF_IN_USE))
 | 
						|
			continue;
 | 
						|
		if(!(ds_subs[i].flags & dsp->flags & DSF_MASK_TYPE))
 | 
						|
			continue;
 | 
						|
 | 
						|
		ep = ds_getprocep(ds_subs[i].owner);
 | 
						|
		if(!check_sub_match(&ds_subs[i], dsp, ep))
 | 
						|
			continue;
 | 
						|
 | 
						|
		if(set == 1) {
 | 
						|
			SET_BIT(ds_subs[i].old_subs, nr);
 | 
						|
		} else {
 | 
						|
			UNSET_BIT(ds_subs[i].old_subs, nr);
 | 
						|
		}
 | 
						|
		ipc_notify(ep);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *		               map_service                                   *
 | 
						|
 *===========================================================================*/
 | 
						|
static int map_service(const struct rprocpub *rpub)
 | 
						|
{
 | 
						|
/* Map a new service by registering its label. */
 | 
						|
  struct data_store *dsp;
 | 
						|
 | 
						|
  /* Allocate a new data slot. */
 | 
						|
  if((dsp = alloc_data_slot()) == NULL) {
 | 
						|
	return ENOMEM;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Set attributes. */
 | 
						|
  strcpy(dsp->key, rpub->label);
 | 
						|
  dsp->u.u32 = (u32_t) rpub->endpoint;
 | 
						|
  strcpy(dsp->owner, "rs");
 | 
						|
  dsp->flags = DSF_IN_USE | DSF_TYPE_LABEL;
 | 
						|
 | 
						|
  /* Update subscribers having a matching subscription. */
 | 
						|
  update_subscribers(dsp, 1);
 | 
						|
 | 
						|
  return(OK);
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *		            sef_cb_init_fresh                                *
 | 
						|
 *===========================================================================*/
 | 
						|
int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
 | 
						|
{
 | 
						|
/* Initialize the data store server. */
 | 
						|
	int i, r;
 | 
						|
	struct rprocpub rprocpub[NR_BOOT_PROCS];
 | 
						|
 | 
						|
	/* Reset data store: data and subscriptions. */
 | 
						|
	for(i = 0; i < NR_DS_KEYS; i++) {
 | 
						|
		ds_store[i].flags = 0;
 | 
						|
	}
 | 
						|
	for(i = 0; i < NR_DS_SUBS; i++) {
 | 
						|
		ds_subs[i].flags = 0;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Map all the services in the boot image. */
 | 
						|
	if((r = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
 | 
						|
		(vir_bytes) rprocpub, sizeof(rprocpub))) != OK) {
 | 
						|
		panic("sys_safecopyfrom failed: %d", r);
 | 
						|
	}
 | 
						|
	for(i=0;i < NR_BOOT_PROCS;i++) {
 | 
						|
		if(rprocpub[i].in_use) {
 | 
						|
			if((r = map_service(&rprocpub[i])) != OK) {
 | 
						|
				panic("unable to map service: %d", r);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return(OK);
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				do_publish				     *
 | 
						|
 *===========================================================================*/
 | 
						|
int do_publish(message *m_ptr)
 | 
						|
{
 | 
						|
  struct data_store *dsp;
 | 
						|
  char key_name[DS_MAX_KEYLEN];
 | 
						|
  char *source;
 | 
						|
  int flags = m_ptr->DS_FLAGS;
 | 
						|
  size_t length;
 | 
						|
  int r;
 | 
						|
 | 
						|
  /* Lookup the source. */
 | 
						|
  source = ds_getprocname(m_ptr->m_source);
 | 
						|
  if(source == NULL)
 | 
						|
	  return EPERM;
 | 
						|
 | 
						|
  /* Only RS can publish labels. */
 | 
						|
  if((flags & DSF_TYPE_LABEL) && m_ptr->m_source != RS_PROC_NR)
 | 
						|
	  return EPERM;
 | 
						|
 | 
						|
  /* Get key name. */
 | 
						|
  if((r = get_key_name(m_ptr, key_name)) != OK)
 | 
						|
	return r;
 | 
						|
 | 
						|
  /* Lookup the entry. */
 | 
						|
  dsp = lookup_entry(key_name, flags & DSF_MASK_TYPE);
 | 
						|
  /* If type is LABEL, also try to lookup the entry by num. */
 | 
						|
  if((flags & DSF_TYPE_LABEL) && (dsp == NULL))
 | 
						|
	dsp = lookup_label_entry(m_ptr->DS_VAL);
 | 
						|
 | 
						|
  if(dsp == NULL) {
 | 
						|
	/* The entry doesn't exist, allocate a new data slot. */
 | 
						|
	if((dsp = alloc_data_slot()) == NULL)
 | 
						|
		return ENOMEM;
 | 
						|
  } else if (flags & DSF_OVERWRITE) {
 | 
						|
	/* Overwrite. */
 | 
						|
	if(!check_auth(dsp, m_ptr->m_source, DSF_PRIV_OVERWRITE))
 | 
						|
		return EPERM;
 | 
						|
  } else {
 | 
						|
	/* Don't overwrite and return error. */
 | 
						|
	return EEXIST;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Store! */
 | 
						|
  switch(flags & DSF_MASK_TYPE) {
 | 
						|
  case DSF_TYPE_U32:
 | 
						|
  case DSF_TYPE_LABEL:
 | 
						|
	dsp->u.u32 = m_ptr->DS_VAL;
 | 
						|
	break;
 | 
						|
  case DSF_TYPE_STR:
 | 
						|
  case DSF_TYPE_MEM:
 | 
						|
	length = m_ptr->DS_VAL_LEN;
 | 
						|
	/* Allocate a new data buffer if necessary. */
 | 
						|
	if(!(dsp->flags & DSF_IN_USE)) {
 | 
						|
		if((dsp->u.mem.data = malloc(length)) == NULL)
 | 
						|
			return ENOMEM;
 | 
						|
		dsp->u.mem.reallen = length;
 | 
						|
	} else if(length > dsp->u.mem.reallen) {
 | 
						|
		free(dsp->u.mem.data);
 | 
						|
		if((dsp->u.mem.data = malloc(length)) == NULL)
 | 
						|
			return ENOMEM;
 | 
						|
		dsp->u.mem.reallen = length;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Copy the memory range. */
 | 
						|
	r = sys_safecopyfrom(m_ptr->m_source, (cp_grant_id_t) m_ptr->DS_VAL,
 | 
						|
	        0, (vir_bytes) dsp->u.mem.data, length);
 | 
						|
	if(r != OK) {
 | 
						|
		printf("DS: publish: memory map/copy failed from %d: %d\n",
 | 
						|
			m_ptr->m_source, r);
 | 
						|
		free(dsp->u.mem.data);
 | 
						|
		return r;
 | 
						|
	}
 | 
						|
	dsp->u.mem.length = length;
 | 
						|
	if(flags & DSF_TYPE_STR) {
 | 
						|
		((char*)dsp->u.mem.data)[length-1] = '\0';
 | 
						|
	}
 | 
						|
	break;
 | 
						|
  default:
 | 
						|
	return EINVAL;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Set attributes. */
 | 
						|
  strcpy(dsp->key, key_name);
 | 
						|
  strcpy(dsp->owner, source);
 | 
						|
  dsp->flags = DSF_IN_USE | (flags & DSF_MASK_INTERNAL);
 | 
						|
 | 
						|
  /* Update subscribers having a matching subscription. */
 | 
						|
  update_subscribers(dsp, 1);
 | 
						|
 | 
						|
  return(OK);
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				do_retrieve				     *
 | 
						|
 *===========================================================================*/
 | 
						|
int do_retrieve(message *m_ptr)
 | 
						|
{
 | 
						|
  struct data_store *dsp;
 | 
						|
  char key_name[DS_MAX_KEYLEN];
 | 
						|
  int flags = m_ptr->DS_FLAGS;
 | 
						|
  int type = flags & DSF_MASK_TYPE;
 | 
						|
  size_t length;
 | 
						|
  int r;
 | 
						|
 | 
						|
  /* Get key name. */
 | 
						|
  if((r = get_key_name(m_ptr, key_name)) != OK)
 | 
						|
	return r;
 | 
						|
 | 
						|
  /* Lookup the entry. */
 | 
						|
  if((dsp = lookup_entry(key_name, type)) == NULL)
 | 
						|
	return ESRCH;
 | 
						|
  if(!check_auth(dsp, m_ptr->m_source, DSF_PRIV_RETRIEVE))
 | 
						|
	return EPERM;
 | 
						|
 | 
						|
  /* Copy the requested data. */
 | 
						|
  switch(type) {
 | 
						|
  case DSF_TYPE_U32:
 | 
						|
  case DSF_TYPE_LABEL:
 | 
						|
	m_ptr->DS_VAL = dsp->u.u32;
 | 
						|
	break;
 | 
						|
  case DSF_TYPE_STR:
 | 
						|
  case DSF_TYPE_MEM:
 | 
						|
	length = MIN(m_ptr->DS_VAL_LEN, dsp->u.mem.length);
 | 
						|
	r = sys_safecopyto(m_ptr->m_source, (cp_grant_id_t) m_ptr->DS_VAL, 0,
 | 
						|
		(vir_bytes) dsp->u.mem.data, length);
 | 
						|
	if(r != OK) {
 | 
						|
		printf("DS: retrieve: copy failed to %d: %d\n",	
 | 
						|
			m_ptr->m_source, r);
 | 
						|
		return r;
 | 
						|
	}
 | 
						|
	m_ptr->DS_VAL_LEN = length;
 | 
						|
	break;
 | 
						|
  default:
 | 
						|
	return EINVAL;
 | 
						|
  }
 | 
						|
 | 
						|
  return OK;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				do_retrieve_label			     *
 | 
						|
 *===========================================================================*/
 | 
						|
int do_retrieve_label(const message *m_ptr)
 | 
						|
{
 | 
						|
  struct data_store *dsp;
 | 
						|
  int r;
 | 
						|
 | 
						|
  /* Lookup the label entry. */
 | 
						|
  if((dsp = lookup_label_entry(m_ptr->DS_VAL)) == NULL)
 | 
						|
	return ESRCH;
 | 
						|
 | 
						|
  /* Copy the key name. */
 | 
						|
  r = sys_safecopyto(m_ptr->m_source,
 | 
						|
	(cp_grant_id_t) m_ptr->DS_KEY_GRANT, (vir_bytes) 0,
 | 
						|
	(vir_bytes) dsp->key, strlen(dsp->key) + 1);
 | 
						|
  if(r != OK) {
 | 
						|
	printf("DS: copy failed from %d: %d\n", m_ptr->m_source, r);
 | 
						|
	return r;
 | 
						|
  }
 | 
						|
 | 
						|
  return OK;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				do_subscribe				     *
 | 
						|
 *===========================================================================*/
 | 
						|
int do_subscribe(message *m_ptr)
 | 
						|
{
 | 
						|
  char regex[DS_MAX_KEYLEN+2];
 | 
						|
  struct subscription *subp;
 | 
						|
  char errbuf[80];
 | 
						|
  char *owner;
 | 
						|
  int type_set;
 | 
						|
  int r, e, b;
 | 
						|
 | 
						|
  /* Find the owner. */
 | 
						|
  owner = ds_getprocname(m_ptr->m_source);
 | 
						|
  if(owner == NULL)
 | 
						|
	  return ESRCH;
 | 
						|
 | 
						|
  /* See if the owner already has an existing subscription. */
 | 
						|
  if((subp = lookup_sub(owner)) == NULL) {
 | 
						|
	/* The subscription doesn't exist, allocate a new one. */
 | 
						|
	if((subp = alloc_sub_slot()) == NULL)
 | 
						|
		return EAGAIN;
 | 
						|
  } else if(!(m_ptr->DS_FLAGS & DSF_OVERWRITE)) {
 | 
						|
	/* The subscription exists but we can't overwrite, return error. */
 | 
						|
	return EEXIST;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Copy key name from the caller. Anchor the subscription with "^regexp$" so
 | 
						|
   * substrings don't match. The caller will probably not expect this,
 | 
						|
   * and the usual case is for a complete match.
 | 
						|
   */
 | 
						|
  regex[0] = '^';
 | 
						|
  if((r = get_key_name(m_ptr, regex+1)) != OK)
 | 
						|
	return r;
 | 
						|
  strcat(regex, "$");
 | 
						|
 | 
						|
  /* Compile regular expression. */
 | 
						|
  if((e=regcomp(&subp->regex, regex, REG_EXTENDED)) != 0) {
 | 
						|
	regerror(e, &subp->regex, errbuf, sizeof(errbuf));
 | 
						|
	printf("DS: subscribe: regerror: %s\n", errbuf);
 | 
						|
	return EINVAL;
 | 
						|
  }
 | 
						|
 | 
						|
  /* If type_set = 0, then subscribe all types. */
 | 
						|
  type_set = m_ptr->DS_FLAGS & DSF_MASK_TYPE;
 | 
						|
  if(type_set == 0)
 | 
						|
	  type_set = DSF_MASK_TYPE;
 | 
						|
 | 
						|
  subp->flags = DSF_IN_USE | type_set;
 | 
						|
  strcpy(subp->owner, owner);
 | 
						|
  for(b = 0; b < BITMAP_CHUNKS(NR_DS_KEYS); b++)
 | 
						|
	subp->old_subs[b] = 0;
 | 
						|
 | 
						|
  /* See if caller requested an instant initial list. */
 | 
						|
  if(m_ptr->DS_FLAGS & DSF_INITIAL) {
 | 
						|
	int i, match_found = FALSE;
 | 
						|
	for(i = 0; i < NR_DS_KEYS; i++) {
 | 
						|
		if(!(ds_store[i].flags & DSF_IN_USE))
 | 
						|
			continue;
 | 
						|
		if(!(ds_store[i].flags & type_set))
 | 
						|
			continue;
 | 
						|
		if(!check_sub_match(subp, &ds_store[i], m_ptr->m_source))
 | 
						|
			continue;
 | 
						|
 | 
						|
		SET_BIT(subp->old_subs, i);
 | 
						|
		match_found = TRUE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Notify in case of match. */
 | 
						|
	if(match_found)
 | 
						|
		ipc_notify(m_ptr->m_source);
 | 
						|
  }
 | 
						|
 | 
						|
  return OK;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				do_check				     *
 | 
						|
 *===========================================================================*/
 | 
						|
int do_check(message *m_ptr)
 | 
						|
{
 | 
						|
  struct subscription *subp;
 | 
						|
  char *owner;
 | 
						|
  endpoint_t entry_owner_e;
 | 
						|
  int r, i;
 | 
						|
 | 
						|
  /* Find the subscription owner. */
 | 
						|
  owner = ds_getprocname(m_ptr->m_source);
 | 
						|
  if(owner == NULL)
 | 
						|
	  return ESRCH;
 | 
						|
 | 
						|
  /* Lookup the owner's subscription. */
 | 
						|
  if((subp = lookup_sub(owner)) == NULL)
 | 
						|
	return ESRCH;
 | 
						|
 | 
						|
  /* Look for an updated entry the subscriber is interested in. */
 | 
						|
  for(i = 0; i < NR_DS_KEYS; i++) {
 | 
						|
	if(GET_BIT(subp->old_subs, i))
 | 
						|
		break;
 | 
						|
  }
 | 
						|
  if(i == NR_DS_KEYS)
 | 
						|
	return ENOENT;
 | 
						|
 | 
						|
  /* Copy the key name. */
 | 
						|
  r = sys_safecopyto(m_ptr->m_source,
 | 
						|
	(cp_grant_id_t) m_ptr->DS_KEY_GRANT, (vir_bytes) 0, 
 | 
						|
	(vir_bytes) ds_store[i].key, strlen(ds_store[i].key) + 1);
 | 
						|
  if(r != OK) {
 | 
						|
	printf("DS: check: copy failed from %d: %d\n", m_ptr->m_source, r);
 | 
						|
	return r;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Copy the type and the owner of the original entry. */
 | 
						|
  entry_owner_e = ds_getprocep(ds_store[i].owner);
 | 
						|
  m_ptr->DS_FLAGS = ds_store[i].flags & DSF_MASK_TYPE;
 | 
						|
  m_ptr->DS_OWNER = entry_owner_e;
 | 
						|
 | 
						|
  /* Mark the entry as no longer updated for the subscriber. */
 | 
						|
  UNSET_BIT(subp->old_subs, i);
 | 
						|
 | 
						|
  return OK;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				do_delete				     *
 | 
						|
 *===========================================================================*/
 | 
						|
int do_delete(message *m_ptr)
 | 
						|
{
 | 
						|
  struct data_store *dsp;
 | 
						|
  char key_name[DS_MAX_KEYLEN];
 | 
						|
  char *source;
 | 
						|
  char *label;
 | 
						|
  int type = m_ptr->DS_FLAGS & DSF_MASK_TYPE;
 | 
						|
  int i, r;
 | 
						|
 | 
						|
  /* Lookup the source. */
 | 
						|
  source = ds_getprocname(m_ptr->m_source);
 | 
						|
  if(source == NULL)
 | 
						|
	  return EPERM;
 | 
						|
 | 
						|
  /* Get key name. */
 | 
						|
  if((r = get_key_name(m_ptr, key_name)) != OK)
 | 
						|
	return r;
 | 
						|
 | 
						|
  /* Lookup the entry. */
 | 
						|
  if((dsp = lookup_entry(key_name, type)) == NULL)
 | 
						|
	return ESRCH;
 | 
						|
 | 
						|
  /* Only the owner can delete. */
 | 
						|
  if(strcmp(dsp->owner, source))
 | 
						|
	return EPERM;
 | 
						|
 | 
						|
  switch(type) {
 | 
						|
  case DSF_TYPE_U32:
 | 
						|
	break;
 | 
						|
  case DSF_TYPE_LABEL:
 | 
						|
	label = dsp->key;
 | 
						|
 | 
						|
	/* Clean up subscriptions. */
 | 
						|
	for (i = 0; i < NR_DS_SUBS; i++) {
 | 
						|
		if ((ds_subs[i].flags & DSF_IN_USE)
 | 
						|
			&& !strcmp(ds_subs[i].owner, label)) {
 | 
						|
			ds_subs[i].flags = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* Clean up data entries. */
 | 
						|
	for (i = 0; i < NR_DS_KEYS; i++) {
 | 
						|
		if ((ds_store[i].flags & DSF_IN_USE)
 | 
						|
			&& !strcmp(ds_store[i].owner, label)) {
 | 
						|
			update_subscribers(&ds_store[i], 0);
 | 
						|
 | 
						|
			ds_store[i].flags = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	break;
 | 
						|
  case DSF_TYPE_STR:
 | 
						|
  case DSF_TYPE_MEM:
 | 
						|
	free(dsp->u.mem.data);
 | 
						|
	break;
 | 
						|
  default:
 | 
						|
	return EINVAL;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Update subscribers having a matching subscription. */
 | 
						|
  update_subscribers(dsp, 0);
 | 
						|
 | 
						|
  /* Clear the entry. */
 | 
						|
  dsp->flags = 0;
 | 
						|
 | 
						|
  return OK;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				do_getsysinfo				     *
 | 
						|
 *===========================================================================*/
 | 
						|
int do_getsysinfo(const message *m_ptr)
 | 
						|
{
 | 
						|
  vir_bytes src_addr;
 | 
						|
  size_t length;
 | 
						|
  int s;
 | 
						|
 | 
						|
  switch(m_ptr->m_lsys_getsysinfo.what) {
 | 
						|
  case SI_DATA_STORE:
 | 
						|
	src_addr = (vir_bytes)ds_store;
 | 
						|
	length = sizeof(struct data_store) * NR_DS_KEYS;
 | 
						|
	break;
 | 
						|
  default:
 | 
						|
  	return EINVAL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (length != m_ptr->m_lsys_getsysinfo.size)
 | 
						|
	return EINVAL;
 | 
						|
 | 
						|
  if (OK != (s=sys_datacopy(SELF, src_addr,
 | 
						|
		m_ptr->m_source, m_ptr->m_lsys_getsysinfo.where, length))) {
 | 
						|
	printf("DS: copy failed: %d\n", s);
 | 
						|
	return s;
 | 
						|
  }
 | 
						|
 | 
						|
  return OK;
 | 
						|
}
 | 
						|
 |