xref: /minix3/minix/servers/ds/store.c (revision 736b88cf53fefc6d498873b8ecf2e9320ec56864)
1433d6423SLionel Sambuc #include "inc.h"
2433d6423SLionel Sambuc #include "store.h"
3433d6423SLionel Sambuc 
4433d6423SLionel Sambuc /* Allocate space for the data store. */
5433d6423SLionel Sambuc static struct data_store ds_store[NR_DS_KEYS];
6433d6423SLionel Sambuc static struct subscription ds_subs[NR_DS_SUBS];
7433d6423SLionel Sambuc 
8433d6423SLionel Sambuc /*===========================================================================*
9433d6423SLionel Sambuc  *			      alloc_data_slot				     *
10433d6423SLionel Sambuc  *===========================================================================*/
alloc_data_slot(void)11433d6423SLionel Sambuc static struct data_store *alloc_data_slot(void)
12433d6423SLionel Sambuc {
13433d6423SLionel Sambuc /* Allocate a new data slot. */
14433d6423SLionel Sambuc   int i;
15433d6423SLionel Sambuc 
16433d6423SLionel Sambuc   for (i = 0; i < NR_DS_KEYS; i++) {
17433d6423SLionel Sambuc 	if (!(ds_store[i].flags & DSF_IN_USE))
18433d6423SLionel Sambuc 		return &ds_store[i];
19433d6423SLionel Sambuc   }
20433d6423SLionel Sambuc 
21433d6423SLionel Sambuc   return NULL;
22433d6423SLionel Sambuc }
23433d6423SLionel Sambuc 
24433d6423SLionel Sambuc /*===========================================================================*
25433d6423SLionel Sambuc  *				alloc_sub_slot				     *
26433d6423SLionel Sambuc  *===========================================================================*/
alloc_sub_slot(void)27433d6423SLionel Sambuc static struct subscription *alloc_sub_slot(void)
28433d6423SLionel Sambuc {
29*736b88cfSDavid van Moolenbroek /* Return a free subscription slot. */
30433d6423SLionel Sambuc   int i;
31433d6423SLionel Sambuc 
32433d6423SLionel Sambuc   for (i = 0; i < NR_DS_SUBS; i++) {
33433d6423SLionel Sambuc 	if (!(ds_subs[i].flags & DSF_IN_USE))
34433d6423SLionel Sambuc 		return &ds_subs[i];
35433d6423SLionel Sambuc   }
36433d6423SLionel Sambuc 
37433d6423SLionel Sambuc   return NULL;
38433d6423SLionel Sambuc }
39433d6423SLionel Sambuc 
40433d6423SLionel Sambuc /*===========================================================================*
41*736b88cfSDavid van Moolenbroek  *				free_sub_slot				     *
42*736b88cfSDavid van Moolenbroek  *===========================================================================*/
free_sub_slot(struct subscription * subp)43*736b88cfSDavid van Moolenbroek static void free_sub_slot(struct subscription *subp)
44*736b88cfSDavid van Moolenbroek {
45*736b88cfSDavid van Moolenbroek /* Clean up a previously successfully) allocated subscription slot. */
46*736b88cfSDavid van Moolenbroek   assert(subp->flags & DSF_IN_USE);
47*736b88cfSDavid van Moolenbroek 
48*736b88cfSDavid van Moolenbroek   regfree(&subp->regex);
49*736b88cfSDavid van Moolenbroek   memset(&subp->regex, 0, sizeof(subp->regex));
50*736b88cfSDavid van Moolenbroek 
51*736b88cfSDavid van Moolenbroek   subp->flags = 0;
52*736b88cfSDavid van Moolenbroek }
53*736b88cfSDavid van Moolenbroek 
54*736b88cfSDavid van Moolenbroek /*===========================================================================*
55433d6423SLionel Sambuc  *				lookup_entry				     *
56433d6423SLionel Sambuc  *===========================================================================*/
lookup_entry(const char * key_name,int type)57433d6423SLionel Sambuc static struct data_store *lookup_entry(const char *key_name, int type)
58433d6423SLionel Sambuc {
59433d6423SLionel Sambuc /* Lookup an existing entry by key and type. */
60433d6423SLionel Sambuc   int i;
61433d6423SLionel Sambuc 
62433d6423SLionel Sambuc   for (i = 0; i < NR_DS_KEYS; i++) {
63433d6423SLionel Sambuc 	if ((ds_store[i].flags & DSF_IN_USE) /* used */
64433d6423SLionel Sambuc 		&& (ds_store[i].flags & type) /* same type*/
65433d6423SLionel Sambuc 		&& !strcmp(ds_store[i].key, key_name)) /* same key*/
66433d6423SLionel Sambuc 		return &ds_store[i];
67433d6423SLionel Sambuc   }
68433d6423SLionel Sambuc 
69433d6423SLionel Sambuc   return NULL;
70433d6423SLionel Sambuc }
71433d6423SLionel Sambuc 
72433d6423SLionel Sambuc /*===========================================================================*
73433d6423SLionel Sambuc  *			     lookup_label_entry				     *
74433d6423SLionel Sambuc  *===========================================================================*/
lookup_label_entry(unsigned num)75433d6423SLionel Sambuc static struct data_store *lookup_label_entry(unsigned num)
76433d6423SLionel Sambuc {
77433d6423SLionel Sambuc /* Lookup an existing label entry by num. */
78433d6423SLionel Sambuc   int i;
79433d6423SLionel Sambuc 
80433d6423SLionel Sambuc   for (i = 0; i < NR_DS_KEYS; i++) {
81433d6423SLionel Sambuc 	if ((ds_store[i].flags & DSF_IN_USE)
82433d6423SLionel Sambuc 		&& (ds_store[i].flags & DSF_TYPE_LABEL)
83433d6423SLionel Sambuc 		&& (ds_store[i].u.u32 == num))
84433d6423SLionel Sambuc 		return &ds_store[i];
85433d6423SLionel Sambuc   }
86433d6423SLionel Sambuc 
87433d6423SLionel Sambuc   return NULL;
88433d6423SLionel Sambuc }
89433d6423SLionel Sambuc 
90433d6423SLionel Sambuc /*===========================================================================*
91433d6423SLionel Sambuc  *			      lookup_sub				     *
92433d6423SLionel Sambuc  *===========================================================================*/
lookup_sub(const char * owner)93433d6423SLionel Sambuc static struct subscription *lookup_sub(const char *owner)
94433d6423SLionel Sambuc {
95433d6423SLionel Sambuc /* Lookup an existing subscription given its owner. */
96433d6423SLionel Sambuc   int i;
97433d6423SLionel Sambuc 
98433d6423SLionel Sambuc   for (i = 0; i < NR_DS_SUBS; i++) {
99433d6423SLionel Sambuc 	if ((ds_subs[i].flags & DSF_IN_USE) /* used */
100433d6423SLionel Sambuc 		&& !strcmp(ds_subs[i].owner, owner)) /* same key*/
101433d6423SLionel Sambuc 		return &ds_subs[i];
102433d6423SLionel Sambuc   }
103433d6423SLionel Sambuc 
104433d6423SLionel Sambuc   return NULL;
105433d6423SLionel Sambuc }
106433d6423SLionel Sambuc 
107433d6423SLionel Sambuc /*===========================================================================*
108433d6423SLionel Sambuc  *				ds_getprocname				     *
109433d6423SLionel Sambuc  *===========================================================================*/
ds_getprocname(endpoint_t e)110433d6423SLionel Sambuc static char *ds_getprocname(endpoint_t e)
111433d6423SLionel Sambuc {
112433d6423SLionel Sambuc /* Get a process name given its endpoint. */
113433d6423SLionel Sambuc 	struct data_store *dsp;
114433d6423SLionel Sambuc 
115433d6423SLionel Sambuc 	static char *first_proc_name = "ds";
116433d6423SLionel Sambuc 	endpoint_t first_proc_ep = DS_PROC_NR;
117433d6423SLionel Sambuc 
118433d6423SLionel Sambuc 	if(e == first_proc_ep)
119433d6423SLionel Sambuc 		return first_proc_name;
120433d6423SLionel Sambuc 
121433d6423SLionel Sambuc 	if((dsp = lookup_label_entry(e)) != NULL)
122433d6423SLionel Sambuc 		return dsp->key;
123433d6423SLionel Sambuc 
124433d6423SLionel Sambuc 	return NULL;
125433d6423SLionel Sambuc }
126433d6423SLionel Sambuc 
127433d6423SLionel Sambuc /*===========================================================================*
128433d6423SLionel Sambuc  *				ds_getprocep				     *
129433d6423SLionel Sambuc  *===========================================================================*/
ds_getprocep(const char * s)130433d6423SLionel Sambuc static endpoint_t ds_getprocep(const char *s)
131433d6423SLionel Sambuc {
132433d6423SLionel Sambuc /* Get a process endpoint given its name. */
133433d6423SLionel Sambuc 	struct data_store *dsp;
134433d6423SLionel Sambuc 
135433d6423SLionel Sambuc 	if((dsp = lookup_entry(s, DSF_TYPE_LABEL)) != NULL)
136433d6423SLionel Sambuc 		return dsp->u.u32;
137433d6423SLionel Sambuc 	panic("ds_getprocep: process endpoint not found");
138433d6423SLionel Sambuc }
139433d6423SLionel Sambuc 
140433d6423SLionel Sambuc /*===========================================================================*
141433d6423SLionel Sambuc  *				 check_auth				     *
142433d6423SLionel Sambuc  *===========================================================================*/
check_auth(const struct data_store * p,endpoint_t ep,int perm)143433d6423SLionel Sambuc static int check_auth(const struct data_store *p, endpoint_t ep, int perm)
144433d6423SLionel Sambuc {
145433d6423SLionel Sambuc /* Check authorization for a given type of permission. */
146433d6423SLionel Sambuc 	char *source;
147433d6423SLionel Sambuc 
148433d6423SLionel Sambuc 	if(!(p->flags & perm))
149433d6423SLionel Sambuc 		return 1;
150433d6423SLionel Sambuc 
151433d6423SLionel Sambuc 	source = ds_getprocname(ep);
152433d6423SLionel Sambuc 	return source && !strcmp(p->owner, source);
153433d6423SLionel Sambuc }
154433d6423SLionel Sambuc 
155433d6423SLionel Sambuc /*===========================================================================*
156433d6423SLionel Sambuc  *				get_key_name				     *
157433d6423SLionel Sambuc  *===========================================================================*/
get_key_name(const message * m_ptr,char * key_name)158433d6423SLionel Sambuc static int get_key_name(const message *m_ptr, char *key_name)
159433d6423SLionel Sambuc {
160433d6423SLionel Sambuc /* Get key name given an input message. */
161433d6423SLionel Sambuc   int r;
162433d6423SLionel Sambuc 
163433d6423SLionel Sambuc   if (m_ptr->m_ds_req.key_len > DS_MAX_KEYLEN || m_ptr->m_ds_req.key_len < 2) {
164433d6423SLionel Sambuc 	printf("DS: bogus key length (%d) from %d\n", m_ptr->m_ds_req.key_len,
165433d6423SLionel Sambuc 		m_ptr->m_source);
166433d6423SLionel Sambuc 	return EINVAL;
167433d6423SLionel Sambuc   }
168433d6423SLionel Sambuc 
169433d6423SLionel Sambuc   /* Copy name from caller. */
170433d6423SLionel Sambuc   r = sys_safecopyfrom(m_ptr->m_source,
171433d6423SLionel Sambuc 	(cp_grant_id_t) m_ptr->m_ds_req.key_grant, 0,
172433d6423SLionel Sambuc 	(vir_bytes) key_name, m_ptr->m_ds_req.key_len);
173433d6423SLionel Sambuc   if(r != OK) {
174433d6423SLionel Sambuc 	printf("DS: publish: copy failed from %d: %d\n", m_ptr->m_source, r);
175433d6423SLionel Sambuc 	return r;
176433d6423SLionel Sambuc   }
177433d6423SLionel Sambuc 
178433d6423SLionel Sambuc   key_name[DS_MAX_KEYLEN-1] = '\0';
179433d6423SLionel Sambuc 
180433d6423SLionel Sambuc   return OK;
181433d6423SLionel Sambuc }
182433d6423SLionel Sambuc 
183433d6423SLionel Sambuc /*===========================================================================*
184433d6423SLionel Sambuc  *				check_sub_match				     *
185433d6423SLionel Sambuc  *===========================================================================*/
check_sub_match(const struct subscription * subp,struct data_store * dsp,endpoint_t ep)186433d6423SLionel Sambuc static int check_sub_match(const struct subscription *subp,
187433d6423SLionel Sambuc 		struct data_store *dsp, endpoint_t ep)
188433d6423SLionel Sambuc {
189433d6423SLionel Sambuc /* Check if an entry matches a subscription. Return 1 in case of match. */
190433d6423SLionel Sambuc   return (check_auth(dsp, ep, DSF_PRIV_SUBSCRIBE)
191433d6423SLionel Sambuc 	  && regexec(&subp->regex, dsp->key, 0, NULL, 0) == 0)
192433d6423SLionel Sambuc 	  ? 1 : 0;
193433d6423SLionel Sambuc }
194433d6423SLionel Sambuc 
195433d6423SLionel Sambuc /*===========================================================================*
196433d6423SLionel Sambuc  *			     update_subscribers				     *
197433d6423SLionel Sambuc  *===========================================================================*/
update_subscribers(struct data_store * dsp,int set)198433d6423SLionel Sambuc static void update_subscribers(struct data_store *dsp, int set)
199433d6423SLionel Sambuc {
200433d6423SLionel Sambuc /* If set = 1, set bit in the sub bitmap of any subscription matching the given
201433d6423SLionel Sambuc  * entry, otherwise clear it. In both cases, notify the subscriber.
202433d6423SLionel Sambuc  */
203433d6423SLionel Sambuc 	int i;
204433d6423SLionel Sambuc 	int nr = dsp - ds_store;
205433d6423SLionel Sambuc 	endpoint_t ep;
206433d6423SLionel Sambuc 
207433d6423SLionel Sambuc 	for(i = 0; i < NR_DS_SUBS; i++) {
208433d6423SLionel Sambuc 		if(!(ds_subs[i].flags & DSF_IN_USE))
209433d6423SLionel Sambuc 			continue;
210433d6423SLionel Sambuc 		if(!(ds_subs[i].flags & dsp->flags & DSF_MASK_TYPE))
211433d6423SLionel Sambuc 			continue;
212433d6423SLionel Sambuc 
213433d6423SLionel Sambuc 		ep = ds_getprocep(ds_subs[i].owner);
214433d6423SLionel Sambuc 		if(!check_sub_match(&ds_subs[i], dsp, ep))
215433d6423SLionel Sambuc 			continue;
216433d6423SLionel Sambuc 
217433d6423SLionel Sambuc 		if(set == 1) {
218433d6423SLionel Sambuc 			SET_BIT(ds_subs[i].old_subs, nr);
219433d6423SLionel Sambuc 		} else {
220433d6423SLionel Sambuc 			UNSET_BIT(ds_subs[i].old_subs, nr);
221433d6423SLionel Sambuc 		}
222433d6423SLionel Sambuc 		ipc_notify(ep);
223433d6423SLionel Sambuc 	}
224433d6423SLionel Sambuc }
225433d6423SLionel Sambuc 
226433d6423SLionel Sambuc /*===========================================================================*
227433d6423SLionel Sambuc  *		               map_service                                   *
228433d6423SLionel Sambuc  *===========================================================================*/
map_service(const struct rprocpub * rpub)229433d6423SLionel Sambuc static int map_service(const struct rprocpub *rpub)
230433d6423SLionel Sambuc {
231433d6423SLionel Sambuc /* Map a new service by registering its label. */
232433d6423SLionel Sambuc   struct data_store *dsp;
233433d6423SLionel Sambuc 
234433d6423SLionel Sambuc   /* Allocate a new data slot. */
235433d6423SLionel Sambuc   if((dsp = alloc_data_slot()) == NULL) {
236433d6423SLionel Sambuc 	return ENOMEM;
237433d6423SLionel Sambuc   }
238433d6423SLionel Sambuc 
239433d6423SLionel Sambuc   /* Set attributes. */
240433d6423SLionel Sambuc   strcpy(dsp->key, rpub->label);
241433d6423SLionel Sambuc   dsp->u.u32 = (u32_t) rpub->endpoint;
242433d6423SLionel Sambuc   strcpy(dsp->owner, "rs");
243433d6423SLionel Sambuc   dsp->flags = DSF_IN_USE | DSF_TYPE_LABEL;
244433d6423SLionel Sambuc 
245433d6423SLionel Sambuc   /* Update subscribers having a matching subscription. */
246433d6423SLionel Sambuc   update_subscribers(dsp, 1);
247433d6423SLionel Sambuc 
248433d6423SLionel Sambuc   return(OK);
249433d6423SLionel Sambuc }
250433d6423SLionel Sambuc 
251433d6423SLionel Sambuc /*===========================================================================*
252433d6423SLionel Sambuc  *		            sef_cb_init_fresh                                *
253433d6423SLionel Sambuc  *===========================================================================*/
sef_cb_init_fresh(int UNUSED (type),sef_init_info_t * info)254433d6423SLionel Sambuc int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
255433d6423SLionel Sambuc {
256433d6423SLionel Sambuc /* Initialize the data store server. */
257433d6423SLionel Sambuc 	int i, r;
258433d6423SLionel Sambuc 	struct rprocpub rprocpub[NR_BOOT_PROCS];
259433d6423SLionel Sambuc 
260433d6423SLionel Sambuc 	/* Reset data store: data and subscriptions. */
261433d6423SLionel Sambuc 	for(i = 0; i < NR_DS_KEYS; i++) {
262433d6423SLionel Sambuc 		ds_store[i].flags = 0;
263433d6423SLionel Sambuc 	}
264433d6423SLionel Sambuc 	for(i = 0; i < NR_DS_SUBS; i++) {
265433d6423SLionel Sambuc 		ds_subs[i].flags = 0;
266433d6423SLionel Sambuc 	}
267433d6423SLionel Sambuc 
268433d6423SLionel Sambuc 	/* Map all the services in the boot image. */
269433d6423SLionel Sambuc 	if((r = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
270433d6423SLionel Sambuc 		(vir_bytes) rprocpub, sizeof(rprocpub))) != OK) {
271433d6423SLionel Sambuc 		panic("sys_safecopyfrom failed: %d", r);
272433d6423SLionel Sambuc 	}
273433d6423SLionel Sambuc 	for(i=0;i < NR_BOOT_PROCS;i++) {
274433d6423SLionel Sambuc 		if(rprocpub[i].in_use) {
275433d6423SLionel Sambuc 			if((r = map_service(&rprocpub[i])) != OK) {
276433d6423SLionel Sambuc 				panic("unable to map service: %d", r);
277433d6423SLionel Sambuc 			}
278433d6423SLionel Sambuc 		}
279433d6423SLionel Sambuc 	}
280433d6423SLionel Sambuc 
281433d6423SLionel Sambuc 	return(OK);
282433d6423SLionel Sambuc }
283433d6423SLionel Sambuc 
284433d6423SLionel Sambuc /*===========================================================================*
285433d6423SLionel Sambuc  *				do_publish				     *
286433d6423SLionel Sambuc  *===========================================================================*/
do_publish(message * m_ptr)287433d6423SLionel Sambuc int do_publish(message *m_ptr)
288433d6423SLionel Sambuc {
289433d6423SLionel Sambuc   struct data_store *dsp;
290433d6423SLionel Sambuc   char key_name[DS_MAX_KEYLEN];
291433d6423SLionel Sambuc   char *source;
292433d6423SLionel Sambuc   int flags = m_ptr->m_ds_req.flags;
293433d6423SLionel Sambuc   size_t length;
294433d6423SLionel Sambuc   int r;
295433d6423SLionel Sambuc 
296433d6423SLionel Sambuc   /* Lookup the source. */
297433d6423SLionel Sambuc   source = ds_getprocname(m_ptr->m_source);
298433d6423SLionel Sambuc   if(source == NULL)
299433d6423SLionel Sambuc 	  return EPERM;
300433d6423SLionel Sambuc 
301433d6423SLionel Sambuc   /* Only RS can publish labels. */
302433d6423SLionel Sambuc   if((flags & DSF_TYPE_LABEL) && m_ptr->m_source != RS_PROC_NR)
303433d6423SLionel Sambuc 	  return EPERM;
304433d6423SLionel Sambuc 
305433d6423SLionel Sambuc   /* Get key name. */
306433d6423SLionel Sambuc   if((r = get_key_name(m_ptr, key_name)) != OK)
307433d6423SLionel Sambuc 	return r;
308433d6423SLionel Sambuc 
309433d6423SLionel Sambuc   /* Lookup the entry. */
310433d6423SLionel Sambuc   dsp = lookup_entry(key_name, flags & DSF_MASK_TYPE);
311433d6423SLionel Sambuc   /* If type is LABEL, also try to lookup the entry by num. */
312433d6423SLionel Sambuc   if((flags & DSF_TYPE_LABEL) && (dsp == NULL))
313433d6423SLionel Sambuc 	dsp = lookup_label_entry(m_ptr->m_ds_req.val_in.ep);
314433d6423SLionel Sambuc 
315433d6423SLionel Sambuc   if(dsp == NULL) {
316433d6423SLionel Sambuc 	/* The entry doesn't exist, allocate a new data slot. */
317433d6423SLionel Sambuc 	if((dsp = alloc_data_slot()) == NULL)
318433d6423SLionel Sambuc 		return ENOMEM;
319433d6423SLionel Sambuc   } else if (flags & DSF_OVERWRITE) {
320433d6423SLionel Sambuc 	/* Overwrite. */
321433d6423SLionel Sambuc 	if(!check_auth(dsp, m_ptr->m_source, DSF_PRIV_OVERWRITE))
322433d6423SLionel Sambuc 		return EPERM;
323433d6423SLionel Sambuc   } else {
324433d6423SLionel Sambuc 	/* Don't overwrite and return error. */
325433d6423SLionel Sambuc 	return EEXIST;
326433d6423SLionel Sambuc   }
327433d6423SLionel Sambuc 
328433d6423SLionel Sambuc   /* Store! */
329433d6423SLionel Sambuc   switch(flags & DSF_MASK_TYPE) {
330433d6423SLionel Sambuc   case DSF_TYPE_U32:
331433d6423SLionel Sambuc 	dsp->u.u32 = m_ptr->m_ds_req.val_in.u32;
332433d6423SLionel Sambuc 	break;
333433d6423SLionel Sambuc   case DSF_TYPE_LABEL:
334433d6423SLionel Sambuc 	dsp->u.u32 = m_ptr->m_ds_req.val_in.ep;
335433d6423SLionel Sambuc 	break;
336433d6423SLionel Sambuc   case DSF_TYPE_STR:
337433d6423SLionel Sambuc   case DSF_TYPE_MEM:
338433d6423SLionel Sambuc 	length = m_ptr->m_ds_req.val_len;
339433d6423SLionel Sambuc 	/* Allocate a new data buffer if necessary. */
340433d6423SLionel Sambuc 	if(!(dsp->flags & DSF_IN_USE)) {
341433d6423SLionel Sambuc 		if((dsp->u.mem.data = malloc(length)) == NULL)
342433d6423SLionel Sambuc 			return ENOMEM;
343433d6423SLionel Sambuc 		dsp->u.mem.reallen = length;
344433d6423SLionel Sambuc 	} else if(length > dsp->u.mem.reallen) {
345433d6423SLionel Sambuc 		free(dsp->u.mem.data);
346433d6423SLionel Sambuc 		if((dsp->u.mem.data = malloc(length)) == NULL)
347433d6423SLionel Sambuc 			return ENOMEM;
348433d6423SLionel Sambuc 		dsp->u.mem.reallen = length;
349433d6423SLionel Sambuc 	}
350433d6423SLionel Sambuc 
351433d6423SLionel Sambuc 	/* Copy the memory range. */
352433d6423SLionel Sambuc 	r = sys_safecopyfrom(m_ptr->m_source, m_ptr->m_ds_req.val_in.grant,
353433d6423SLionel Sambuc 	        0, (vir_bytes) dsp->u.mem.data, length);
354433d6423SLionel Sambuc 	if(r != OK) {
355433d6423SLionel Sambuc 		printf("DS: publish: memory map/copy failed from %d: %d\n",
356433d6423SLionel Sambuc 			m_ptr->m_source, r);
357433d6423SLionel Sambuc 		free(dsp->u.mem.data);
358433d6423SLionel Sambuc 		return r;
359433d6423SLionel Sambuc 	}
360433d6423SLionel Sambuc 	dsp->u.mem.length = length;
361433d6423SLionel Sambuc 	if(flags & DSF_TYPE_STR) {
362433d6423SLionel Sambuc 		((char*)dsp->u.mem.data)[length-1] = '\0';
363433d6423SLionel Sambuc 	}
364433d6423SLionel Sambuc 	break;
365433d6423SLionel Sambuc   default:
366433d6423SLionel Sambuc 	return EINVAL;
367433d6423SLionel Sambuc   }
368433d6423SLionel Sambuc 
369433d6423SLionel Sambuc   /* Set attributes. */
370433d6423SLionel Sambuc   strcpy(dsp->key, key_name);
371433d6423SLionel Sambuc   strcpy(dsp->owner, source);
372433d6423SLionel Sambuc   dsp->flags = DSF_IN_USE | (flags & DSF_MASK_INTERNAL);
373433d6423SLionel Sambuc 
374433d6423SLionel Sambuc   /* Update subscribers having a matching subscription. */
375433d6423SLionel Sambuc   update_subscribers(dsp, 1);
376433d6423SLionel Sambuc 
377433d6423SLionel Sambuc   return(OK);
378433d6423SLionel Sambuc }
379433d6423SLionel Sambuc 
380433d6423SLionel Sambuc /*===========================================================================*
381433d6423SLionel Sambuc  *				do_retrieve				     *
382433d6423SLionel Sambuc  *===========================================================================*/
do_retrieve(message * m_ptr)383433d6423SLionel Sambuc int do_retrieve(message *m_ptr)
384433d6423SLionel Sambuc {
385433d6423SLionel Sambuc   struct data_store *dsp;
386433d6423SLionel Sambuc   char key_name[DS_MAX_KEYLEN];
387433d6423SLionel Sambuc   int flags = m_ptr->m_ds_req.flags;
388433d6423SLionel Sambuc   int type = flags & DSF_MASK_TYPE;
389433d6423SLionel Sambuc   size_t length;
390433d6423SLionel Sambuc   int r;
391433d6423SLionel Sambuc 
392433d6423SLionel Sambuc   /* Get key name. */
393433d6423SLionel Sambuc   if((r = get_key_name(m_ptr, key_name)) != OK)
394433d6423SLionel Sambuc 	return r;
395433d6423SLionel Sambuc 
396433d6423SLionel Sambuc   /* Lookup the entry. */
397433d6423SLionel Sambuc   if((dsp = lookup_entry(key_name, type)) == NULL)
398433d6423SLionel Sambuc 	return ESRCH;
399433d6423SLionel Sambuc   if(!check_auth(dsp, m_ptr->m_source, DSF_PRIV_RETRIEVE))
400433d6423SLionel Sambuc 	return EPERM;
401433d6423SLionel Sambuc 
402433d6423SLionel Sambuc   /* Copy the requested data. */
403433d6423SLionel Sambuc   switch(type) {
404433d6423SLionel Sambuc   case DSF_TYPE_U32:
405433d6423SLionel Sambuc 	m_ptr->m_ds_reply.val_out.u32 = dsp->u.u32;
406433d6423SLionel Sambuc 	break;
407433d6423SLionel Sambuc   case DSF_TYPE_LABEL:
408433d6423SLionel Sambuc 	m_ptr->m_ds_reply.val_out.ep = dsp->u.u32;
409433d6423SLionel Sambuc 	break;
410433d6423SLionel Sambuc   case DSF_TYPE_STR:
411433d6423SLionel Sambuc   case DSF_TYPE_MEM:
412433d6423SLionel Sambuc 	length = MIN(m_ptr->m_ds_req.val_len, dsp->u.mem.length);
413433d6423SLionel Sambuc 	r = sys_safecopyto(m_ptr->m_source, m_ptr->m_ds_req.val_in.grant, 0,
414433d6423SLionel Sambuc 		(vir_bytes) dsp->u.mem.data, length);
415433d6423SLionel Sambuc 	if(r != OK) {
416433d6423SLionel Sambuc 		printf("DS: retrieve: copy failed to %d: %d\n",
417433d6423SLionel Sambuc 			m_ptr->m_source, r);
418433d6423SLionel Sambuc 		return r;
419433d6423SLionel Sambuc 	}
420433d6423SLionel Sambuc 	m_ptr->m_ds_reply.val_len = length;
421433d6423SLionel Sambuc 	break;
422433d6423SLionel Sambuc   default:
423433d6423SLionel Sambuc 	return EINVAL;
424433d6423SLionel Sambuc   }
425433d6423SLionel Sambuc 
426433d6423SLionel Sambuc   return OK;
427433d6423SLionel Sambuc }
428433d6423SLionel Sambuc 
429433d6423SLionel Sambuc /*===========================================================================*
430433d6423SLionel Sambuc  *				do_retrieve_label			     *
431433d6423SLionel Sambuc  *===========================================================================*/
do_retrieve_label(const message * m_ptr)432433d6423SLionel Sambuc int do_retrieve_label(const message *m_ptr)
433433d6423SLionel Sambuc {
434433d6423SLionel Sambuc   struct data_store *dsp;
435433d6423SLionel Sambuc   int r;
436433d6423SLionel Sambuc 
437433d6423SLionel Sambuc   /* Lookup the label entry. */
438433d6423SLionel Sambuc   if((dsp = lookup_label_entry(m_ptr->m_ds_req.val_in.ep)) == NULL)
439433d6423SLionel Sambuc 	return ESRCH;
440433d6423SLionel Sambuc 
441433d6423SLionel Sambuc   /* Copy the key name. */
442433d6423SLionel Sambuc   r = sys_safecopyto(m_ptr->m_source,
443433d6423SLionel Sambuc 	(cp_grant_id_t) m_ptr->m_ds_req.key_grant, (vir_bytes) 0,
444433d6423SLionel Sambuc 	(vir_bytes) dsp->key, strlen(dsp->key) + 1);
445433d6423SLionel Sambuc   if(r != OK) {
446433d6423SLionel Sambuc 	printf("DS: copy failed from %d: %d\n", m_ptr->m_source, r);
447433d6423SLionel Sambuc 	return r;
448433d6423SLionel Sambuc   }
449433d6423SLionel Sambuc 
450433d6423SLionel Sambuc   return OK;
451433d6423SLionel Sambuc }
452433d6423SLionel Sambuc 
453433d6423SLionel Sambuc /*===========================================================================*
454433d6423SLionel Sambuc  *				do_subscribe				     *
455433d6423SLionel Sambuc  *===========================================================================*/
do_subscribe(message * m_ptr)456433d6423SLionel Sambuc int do_subscribe(message *m_ptr)
457433d6423SLionel Sambuc {
458433d6423SLionel Sambuc   char regex[DS_MAX_KEYLEN+2];
459433d6423SLionel Sambuc   struct subscription *subp;
460433d6423SLionel Sambuc   char errbuf[80];
461433d6423SLionel Sambuc   char *owner;
462433d6423SLionel Sambuc   int type_set;
463433d6423SLionel Sambuc   int r, e, b;
464433d6423SLionel Sambuc 
465433d6423SLionel Sambuc   /* Find the owner. */
466433d6423SLionel Sambuc   owner = ds_getprocname(m_ptr->m_source);
467433d6423SLionel Sambuc   if(owner == NULL)
468433d6423SLionel Sambuc 	  return ESRCH;
469433d6423SLionel Sambuc 
470433d6423SLionel Sambuc   /* See if the owner already has an existing subscription. */
471*736b88cfSDavid van Moolenbroek   if ((subp = lookup_sub(owner)) != NULL) {
472*736b88cfSDavid van Moolenbroek 	/* If a subscription exists but we can't overwrite, return error. */
473*736b88cfSDavid van Moolenbroek 	if (!(m_ptr->m_ds_req.flags & DSF_OVERWRITE))
474*736b88cfSDavid van Moolenbroek 		return EEXIST;
475*736b88cfSDavid van Moolenbroek 	/* Otherwise just free the old one. */
476*736b88cfSDavid van Moolenbroek 	free_sub_slot(subp);
477*736b88cfSDavid van Moolenbroek   }
478*736b88cfSDavid van Moolenbroek 
479*736b88cfSDavid van Moolenbroek   /* Find a free subscription slot. */
480433d6423SLionel Sambuc   if ((subp = alloc_sub_slot()) == NULL)
481433d6423SLionel Sambuc 	return EAGAIN;
482433d6423SLionel Sambuc 
483433d6423SLionel Sambuc   /* Copy key name from the caller. Anchor the subscription with "^regexp$" so
484433d6423SLionel Sambuc    * substrings don't match. The caller will probably not expect this,
485433d6423SLionel Sambuc    * and the usual case is for a complete match.
486433d6423SLionel Sambuc    */
487433d6423SLionel Sambuc   regex[0] = '^';
488433d6423SLionel Sambuc   if((r = get_key_name(m_ptr, regex+1)) != OK)
489433d6423SLionel Sambuc 	return r;
490433d6423SLionel Sambuc   strcat(regex, "$");
491433d6423SLionel Sambuc 
492433d6423SLionel Sambuc   /* Compile regular expression. */
493433d6423SLionel Sambuc   if((e=regcomp(&subp->regex, regex, REG_EXTENDED)) != 0) {
494433d6423SLionel Sambuc 	regerror(e, &subp->regex, errbuf, sizeof(errbuf));
495433d6423SLionel Sambuc 	printf("DS: subscribe: regerror: %s\n", errbuf);
496*736b88cfSDavid van Moolenbroek 	memset(&subp->regex, 0, sizeof(subp->regex));
497433d6423SLionel Sambuc 	return EINVAL;
498433d6423SLionel Sambuc   }
499433d6423SLionel Sambuc 
500433d6423SLionel Sambuc   /* If type_set = 0, then subscribe all types. */
501433d6423SLionel Sambuc   type_set = m_ptr->m_ds_req.flags & DSF_MASK_TYPE;
502433d6423SLionel Sambuc   if(type_set == 0)
503433d6423SLionel Sambuc 	  type_set = DSF_MASK_TYPE;
504433d6423SLionel Sambuc 
505433d6423SLionel Sambuc   subp->flags = DSF_IN_USE | type_set;
506433d6423SLionel Sambuc   strcpy(subp->owner, owner);
507433d6423SLionel Sambuc   for(b = 0; b < BITMAP_CHUNKS(NR_DS_KEYS); b++)
508433d6423SLionel Sambuc 	subp->old_subs[b] = 0;
509433d6423SLionel Sambuc 
510433d6423SLionel Sambuc   /* See if caller requested an instant initial list. */
511433d6423SLionel Sambuc   if(m_ptr->m_ds_req.flags & DSF_INITIAL) {
512433d6423SLionel Sambuc 	int i, match_found = FALSE;
513433d6423SLionel Sambuc 	for(i = 0; i < NR_DS_KEYS; i++) {
514433d6423SLionel Sambuc 		if(!(ds_store[i].flags & DSF_IN_USE))
515433d6423SLionel Sambuc 			continue;
516433d6423SLionel Sambuc 		if(!(ds_store[i].flags & type_set))
517433d6423SLionel Sambuc 			continue;
518433d6423SLionel Sambuc 		if(!check_sub_match(subp, &ds_store[i], m_ptr->m_source))
519433d6423SLionel Sambuc 			continue;
520433d6423SLionel Sambuc 
521433d6423SLionel Sambuc 		SET_BIT(subp->old_subs, i);
522433d6423SLionel Sambuc 		match_found = TRUE;
523433d6423SLionel Sambuc 	}
524433d6423SLionel Sambuc 
525433d6423SLionel Sambuc 	/* Notify in case of match. */
526433d6423SLionel Sambuc 	if(match_found)
527433d6423SLionel Sambuc 		ipc_notify(m_ptr->m_source);
528433d6423SLionel Sambuc   }
529433d6423SLionel Sambuc 
530433d6423SLionel Sambuc   return OK;
531433d6423SLionel Sambuc }
532433d6423SLionel Sambuc 
533433d6423SLionel Sambuc /*===========================================================================*
534433d6423SLionel Sambuc  *				do_check				     *
535433d6423SLionel Sambuc  *===========================================================================*/
do_check(message * m_ptr)536433d6423SLionel Sambuc int do_check(message *m_ptr)
537433d6423SLionel Sambuc {
538433d6423SLionel Sambuc   struct subscription *subp;
539433d6423SLionel Sambuc   char *owner;
540433d6423SLionel Sambuc   endpoint_t entry_owner_e;
541433d6423SLionel Sambuc   int r, i;
542433d6423SLionel Sambuc 
543433d6423SLionel Sambuc   /* Find the subscription owner. */
544433d6423SLionel Sambuc   owner = ds_getprocname(m_ptr->m_source);
545433d6423SLionel Sambuc   if(owner == NULL)
546433d6423SLionel Sambuc 	  return ESRCH;
547433d6423SLionel Sambuc 
548433d6423SLionel Sambuc   /* Lookup the owner's subscription. */
549433d6423SLionel Sambuc   if((subp = lookup_sub(owner)) == NULL)
550433d6423SLionel Sambuc 	return ESRCH;
551433d6423SLionel Sambuc 
552433d6423SLionel Sambuc   /* Look for an updated entry the subscriber is interested in. */
553433d6423SLionel Sambuc   for(i = 0; i < NR_DS_KEYS; i++) {
554433d6423SLionel Sambuc 	if(GET_BIT(subp->old_subs, i))
555433d6423SLionel Sambuc 		break;
556433d6423SLionel Sambuc   }
557433d6423SLionel Sambuc   if(i == NR_DS_KEYS)
558433d6423SLionel Sambuc 	return ENOENT;
559433d6423SLionel Sambuc 
560433d6423SLionel Sambuc   /* Copy the key name. */
561433d6423SLionel Sambuc   r = sys_safecopyto(m_ptr->m_source,
562433d6423SLionel Sambuc 	(cp_grant_id_t) m_ptr->m_ds_req.key_grant, (vir_bytes) 0,
563433d6423SLionel Sambuc 	(vir_bytes) ds_store[i].key, strlen(ds_store[i].key) + 1);
564433d6423SLionel Sambuc   if(r != OK) {
565433d6423SLionel Sambuc 	printf("DS: check: copy failed from %d: %d\n", m_ptr->m_source, r);
566433d6423SLionel Sambuc 	return r;
567433d6423SLionel Sambuc   }
568433d6423SLionel Sambuc 
569433d6423SLionel Sambuc   /* Copy the type and the owner of the original entry. */
570433d6423SLionel Sambuc   entry_owner_e = ds_getprocep(ds_store[i].owner);
571433d6423SLionel Sambuc   m_ptr->m_ds_req.flags = ds_store[i].flags & DSF_MASK_TYPE;
572433d6423SLionel Sambuc   m_ptr->m_ds_req.owner = entry_owner_e;
573433d6423SLionel Sambuc 
574433d6423SLionel Sambuc   /* Mark the entry as no longer updated for the subscriber. */
575433d6423SLionel Sambuc   UNSET_BIT(subp->old_subs, i);
576433d6423SLionel Sambuc 
577433d6423SLionel Sambuc   return OK;
578433d6423SLionel Sambuc }
579433d6423SLionel Sambuc 
580433d6423SLionel Sambuc /*===========================================================================*
581433d6423SLionel Sambuc  *				do_delete				     *
582433d6423SLionel Sambuc  *===========================================================================*/
do_delete(message * m_ptr)583433d6423SLionel Sambuc int do_delete(message *m_ptr)
584433d6423SLionel Sambuc {
585433d6423SLionel Sambuc   struct data_store *dsp;
586433d6423SLionel Sambuc   char key_name[DS_MAX_KEYLEN];
587433d6423SLionel Sambuc   char *source;
588433d6423SLionel Sambuc   char *label;
589433d6423SLionel Sambuc   int type = m_ptr->m_ds_req.flags & DSF_MASK_TYPE;
590433d6423SLionel Sambuc   int i, r;
591433d6423SLionel Sambuc 
592433d6423SLionel Sambuc   /* Lookup the source. */
593433d6423SLionel Sambuc   source = ds_getprocname(m_ptr->m_source);
594433d6423SLionel Sambuc   if(source == NULL)
595433d6423SLionel Sambuc 	  return EPERM;
596433d6423SLionel Sambuc 
597433d6423SLionel Sambuc   /* Get key name. */
598433d6423SLionel Sambuc   if((r = get_key_name(m_ptr, key_name)) != OK)
599433d6423SLionel Sambuc 	return r;
600433d6423SLionel Sambuc 
601433d6423SLionel Sambuc   /* Lookup the entry. */
602433d6423SLionel Sambuc   if((dsp = lookup_entry(key_name, type)) == NULL)
603433d6423SLionel Sambuc 	return ESRCH;
604433d6423SLionel Sambuc 
605433d6423SLionel Sambuc   /* Only the owner can delete. */
606433d6423SLionel Sambuc   if(strcmp(dsp->owner, source))
607433d6423SLionel Sambuc 	return EPERM;
608433d6423SLionel Sambuc 
609433d6423SLionel Sambuc   switch(type) {
610433d6423SLionel Sambuc   case DSF_TYPE_U32:
611433d6423SLionel Sambuc 	break;
612433d6423SLionel Sambuc   case DSF_TYPE_LABEL:
613433d6423SLionel Sambuc 	label = dsp->key;
614433d6423SLionel Sambuc 
615433d6423SLionel Sambuc 	/* Clean up subscriptions. */
616433d6423SLionel Sambuc 	for (i = 0; i < NR_DS_SUBS; i++) {
617433d6423SLionel Sambuc 		if ((ds_subs[i].flags & DSF_IN_USE)
618433d6423SLionel Sambuc 			&& !strcmp(ds_subs[i].owner, label)) {
619*736b88cfSDavid van Moolenbroek 			free_sub_slot(&ds_subs[i]);
620433d6423SLionel Sambuc 		}
621433d6423SLionel Sambuc 	}
622433d6423SLionel Sambuc 
623433d6423SLionel Sambuc 	/* Clean up data entries. */
624433d6423SLionel Sambuc 	for (i = 0; i < NR_DS_KEYS; i++) {
625433d6423SLionel Sambuc 		if ((ds_store[i].flags & DSF_IN_USE)
626433d6423SLionel Sambuc 			&& !strcmp(ds_store[i].owner, label)) {
627433d6423SLionel Sambuc 			update_subscribers(&ds_store[i], 0);
628433d6423SLionel Sambuc 
629433d6423SLionel Sambuc 			ds_store[i].flags = 0;
630433d6423SLionel Sambuc 		}
631433d6423SLionel Sambuc 	}
632433d6423SLionel Sambuc 	break;
633433d6423SLionel Sambuc   case DSF_TYPE_STR:
634433d6423SLionel Sambuc   case DSF_TYPE_MEM:
635433d6423SLionel Sambuc 	free(dsp->u.mem.data);
636433d6423SLionel Sambuc 	break;
637433d6423SLionel Sambuc   default:
638433d6423SLionel Sambuc 	return EINVAL;
639433d6423SLionel Sambuc   }
640433d6423SLionel Sambuc 
641433d6423SLionel Sambuc   /* Update subscribers having a matching subscription. */
642433d6423SLionel Sambuc   update_subscribers(dsp, 0);
643433d6423SLionel Sambuc 
644433d6423SLionel Sambuc   /* Clear the entry. */
645433d6423SLionel Sambuc   dsp->flags = 0;
646433d6423SLionel Sambuc 
647433d6423SLionel Sambuc   return OK;
648433d6423SLionel Sambuc }
649433d6423SLionel Sambuc 
650433d6423SLionel Sambuc /*===========================================================================*
651433d6423SLionel Sambuc  *				do_getsysinfo				     *
652433d6423SLionel Sambuc  *===========================================================================*/
do_getsysinfo(const message * m_ptr)653433d6423SLionel Sambuc int do_getsysinfo(const message *m_ptr)
654433d6423SLionel Sambuc {
655433d6423SLionel Sambuc   vir_bytes src_addr;
656433d6423SLionel Sambuc   size_t length;
657433d6423SLionel Sambuc   int s;
658433d6423SLionel Sambuc 
659433d6423SLionel Sambuc   switch(m_ptr->m_lsys_getsysinfo.what) {
660433d6423SLionel Sambuc   case SI_DATA_STORE:
661433d6423SLionel Sambuc 	src_addr = (vir_bytes)ds_store;
662433d6423SLionel Sambuc 	length = sizeof(struct data_store) * NR_DS_KEYS;
663433d6423SLionel Sambuc 	break;
664433d6423SLionel Sambuc   default:
665433d6423SLionel Sambuc   	return EINVAL;
666433d6423SLionel Sambuc   }
667433d6423SLionel Sambuc 
668433d6423SLionel Sambuc   if (length != m_ptr->m_lsys_getsysinfo.size)
669433d6423SLionel Sambuc 	return EINVAL;
670433d6423SLionel Sambuc 
671433d6423SLionel Sambuc   if (OK != (s=sys_datacopy(SELF, src_addr,
672433d6423SLionel Sambuc 		m_ptr->m_source, m_ptr->m_lsys_getsysinfo.where, length))) {
673433d6423SLionel Sambuc 	printf("DS: copy failed: %d\n", s);
674433d6423SLionel Sambuc 	return s;
675433d6423SLionel Sambuc   }
676433d6423SLionel Sambuc 
677433d6423SLionel Sambuc   return OK;
678433d6423SLionel Sambuc }
679433d6423SLionel Sambuc 
680