xref: /minix3/minix/servers/ds/store.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc #include "inc.h"
2*433d6423SLionel Sambuc #include "store.h"
3*433d6423SLionel Sambuc 
4*433d6423SLionel Sambuc /* Allocate space for the data store. */
5*433d6423SLionel Sambuc static struct data_store ds_store[NR_DS_KEYS];
6*433d6423SLionel Sambuc static struct subscription ds_subs[NR_DS_SUBS];
7*433d6423SLionel Sambuc 
8*433d6423SLionel Sambuc /*===========================================================================*
9*433d6423SLionel Sambuc  *			      alloc_data_slot				     *
10*433d6423SLionel Sambuc  *===========================================================================*/
11*433d6423SLionel Sambuc static struct data_store *alloc_data_slot(void)
12*433d6423SLionel Sambuc {
13*433d6423SLionel Sambuc /* Allocate a new data slot. */
14*433d6423SLionel Sambuc   int i;
15*433d6423SLionel Sambuc 
16*433d6423SLionel Sambuc   for (i = 0; i < NR_DS_KEYS; i++) {
17*433d6423SLionel Sambuc 	if (!(ds_store[i].flags & DSF_IN_USE))
18*433d6423SLionel Sambuc 		return &ds_store[i];
19*433d6423SLionel Sambuc   }
20*433d6423SLionel Sambuc 
21*433d6423SLionel Sambuc   return NULL;
22*433d6423SLionel Sambuc }
23*433d6423SLionel Sambuc 
24*433d6423SLionel Sambuc /*===========================================================================*
25*433d6423SLionel Sambuc  *				alloc_sub_slot				     *
26*433d6423SLionel Sambuc  *===========================================================================*/
27*433d6423SLionel Sambuc static struct subscription *alloc_sub_slot(void)
28*433d6423SLionel Sambuc {
29*433d6423SLionel Sambuc /* Allocate a new subscription slot. */
30*433d6423SLionel Sambuc   int i;
31*433d6423SLionel Sambuc 
32*433d6423SLionel Sambuc   for (i = 0; i < NR_DS_SUBS; i++) {
33*433d6423SLionel Sambuc 	if (!(ds_subs[i].flags & DSF_IN_USE))
34*433d6423SLionel Sambuc 		return &ds_subs[i];
35*433d6423SLionel Sambuc   }
36*433d6423SLionel Sambuc 
37*433d6423SLionel Sambuc   return NULL;
38*433d6423SLionel Sambuc }
39*433d6423SLionel Sambuc 
40*433d6423SLionel Sambuc /*===========================================================================*
41*433d6423SLionel Sambuc  *				lookup_entry				     *
42*433d6423SLionel Sambuc  *===========================================================================*/
43*433d6423SLionel Sambuc static struct data_store *lookup_entry(const char *key_name, int type)
44*433d6423SLionel Sambuc {
45*433d6423SLionel Sambuc /* Lookup an existing entry by key and type. */
46*433d6423SLionel Sambuc   int i;
47*433d6423SLionel Sambuc 
48*433d6423SLionel Sambuc   for (i = 0; i < NR_DS_KEYS; i++) {
49*433d6423SLionel Sambuc 	if ((ds_store[i].flags & DSF_IN_USE) /* used */
50*433d6423SLionel Sambuc 		&& (ds_store[i].flags & type) /* same type*/
51*433d6423SLionel Sambuc 		&& !strcmp(ds_store[i].key, key_name)) /* same key*/
52*433d6423SLionel Sambuc 		return &ds_store[i];
53*433d6423SLionel Sambuc   }
54*433d6423SLionel Sambuc 
55*433d6423SLionel Sambuc   return NULL;
56*433d6423SLionel Sambuc }
57*433d6423SLionel Sambuc 
58*433d6423SLionel Sambuc /*===========================================================================*
59*433d6423SLionel Sambuc  *			     lookup_label_entry				     *
60*433d6423SLionel Sambuc  *===========================================================================*/
61*433d6423SLionel Sambuc static struct data_store *lookup_label_entry(unsigned num)
62*433d6423SLionel Sambuc {
63*433d6423SLionel Sambuc /* Lookup an existing label entry by num. */
64*433d6423SLionel Sambuc   int i;
65*433d6423SLionel Sambuc 
66*433d6423SLionel Sambuc   for (i = 0; i < NR_DS_KEYS; i++) {
67*433d6423SLionel Sambuc 	if ((ds_store[i].flags & DSF_IN_USE)
68*433d6423SLionel Sambuc 		&& (ds_store[i].flags & DSF_TYPE_LABEL)
69*433d6423SLionel Sambuc 		&& (ds_store[i].u.u32 == num))
70*433d6423SLionel Sambuc 		return &ds_store[i];
71*433d6423SLionel Sambuc   }
72*433d6423SLionel Sambuc 
73*433d6423SLionel Sambuc   return NULL;
74*433d6423SLionel Sambuc }
75*433d6423SLionel Sambuc 
76*433d6423SLionel Sambuc /*===========================================================================*
77*433d6423SLionel Sambuc  *			      lookup_sub				     *
78*433d6423SLionel Sambuc  *===========================================================================*/
79*433d6423SLionel Sambuc static struct subscription *lookup_sub(const char *owner)
80*433d6423SLionel Sambuc {
81*433d6423SLionel Sambuc /* Lookup an existing subscription given its owner. */
82*433d6423SLionel Sambuc   int i;
83*433d6423SLionel Sambuc 
84*433d6423SLionel Sambuc   for (i = 0; i < NR_DS_SUBS; i++) {
85*433d6423SLionel Sambuc 	if ((ds_subs[i].flags & DSF_IN_USE) /* used */
86*433d6423SLionel Sambuc 		&& !strcmp(ds_subs[i].owner, owner)) /* same key*/
87*433d6423SLionel Sambuc 		return &ds_subs[i];
88*433d6423SLionel Sambuc   }
89*433d6423SLionel Sambuc 
90*433d6423SLionel Sambuc   return NULL;
91*433d6423SLionel Sambuc }
92*433d6423SLionel Sambuc 
93*433d6423SLionel Sambuc /*===========================================================================*
94*433d6423SLionel Sambuc  *				ds_getprocname				     *
95*433d6423SLionel Sambuc  *===========================================================================*/
96*433d6423SLionel Sambuc static char *ds_getprocname(endpoint_t e)
97*433d6423SLionel Sambuc {
98*433d6423SLionel Sambuc /* Get a process name given its endpoint. */
99*433d6423SLionel Sambuc 	struct data_store *dsp;
100*433d6423SLionel Sambuc 
101*433d6423SLionel Sambuc 	static char *first_proc_name = "ds";
102*433d6423SLionel Sambuc 	endpoint_t first_proc_ep = DS_PROC_NR;
103*433d6423SLionel Sambuc 
104*433d6423SLionel Sambuc 	if(e == first_proc_ep)
105*433d6423SLionel Sambuc 		return first_proc_name;
106*433d6423SLionel Sambuc 
107*433d6423SLionel Sambuc 	if((dsp = lookup_label_entry(e)) != NULL)
108*433d6423SLionel Sambuc 		return dsp->key;
109*433d6423SLionel Sambuc 
110*433d6423SLionel Sambuc 	return NULL;
111*433d6423SLionel Sambuc }
112*433d6423SLionel Sambuc 
113*433d6423SLionel Sambuc /*===========================================================================*
114*433d6423SLionel Sambuc  *				ds_getprocep				     *
115*433d6423SLionel Sambuc  *===========================================================================*/
116*433d6423SLionel Sambuc static endpoint_t ds_getprocep(const char *s)
117*433d6423SLionel Sambuc {
118*433d6423SLionel Sambuc /* Get a process endpoint given its name. */
119*433d6423SLionel Sambuc 	struct data_store *dsp;
120*433d6423SLionel Sambuc 
121*433d6423SLionel Sambuc 	if((dsp = lookup_entry(s, DSF_TYPE_LABEL)) != NULL)
122*433d6423SLionel Sambuc 		return dsp->u.u32;
123*433d6423SLionel Sambuc 	panic("ds_getprocep: process endpoint not found");
124*433d6423SLionel Sambuc }
125*433d6423SLionel Sambuc 
126*433d6423SLionel Sambuc /*===========================================================================*
127*433d6423SLionel Sambuc  *				 check_auth				     *
128*433d6423SLionel Sambuc  *===========================================================================*/
129*433d6423SLionel Sambuc static int check_auth(const struct data_store *p, endpoint_t ep, int perm)
130*433d6423SLionel Sambuc {
131*433d6423SLionel Sambuc /* Check authorization for a given type of permission. */
132*433d6423SLionel Sambuc 	char *source;
133*433d6423SLionel Sambuc 
134*433d6423SLionel Sambuc 	if(!(p->flags & perm))
135*433d6423SLionel Sambuc 		return 1;
136*433d6423SLionel Sambuc 
137*433d6423SLionel Sambuc 	source = ds_getprocname(ep);
138*433d6423SLionel Sambuc 	return source && !strcmp(p->owner, source);
139*433d6423SLionel Sambuc }
140*433d6423SLionel Sambuc 
141*433d6423SLionel Sambuc /*===========================================================================*
142*433d6423SLionel Sambuc  *				get_key_name				     *
143*433d6423SLionel Sambuc  *===========================================================================*/
144*433d6423SLionel Sambuc static int get_key_name(const message *m_ptr, char *key_name)
145*433d6423SLionel Sambuc {
146*433d6423SLionel Sambuc /* Get key name given an input message. */
147*433d6423SLionel Sambuc   int r;
148*433d6423SLionel Sambuc 
149*433d6423SLionel Sambuc   if (m_ptr->m_ds_req.key_len > DS_MAX_KEYLEN || m_ptr->m_ds_req.key_len < 2) {
150*433d6423SLionel Sambuc 	printf("DS: bogus key length (%d) from %d\n", m_ptr->m_ds_req.key_len,
151*433d6423SLionel Sambuc 		m_ptr->m_source);
152*433d6423SLionel Sambuc 	return EINVAL;
153*433d6423SLionel Sambuc   }
154*433d6423SLionel Sambuc 
155*433d6423SLionel Sambuc   /* Copy name from caller. */
156*433d6423SLionel Sambuc   r = sys_safecopyfrom(m_ptr->m_source,
157*433d6423SLionel Sambuc 	(cp_grant_id_t) m_ptr->m_ds_req.key_grant, 0,
158*433d6423SLionel Sambuc 	(vir_bytes) key_name, m_ptr->m_ds_req.key_len);
159*433d6423SLionel Sambuc   if(r != OK) {
160*433d6423SLionel Sambuc 	printf("DS: publish: copy failed from %d: %d\n", m_ptr->m_source, r);
161*433d6423SLionel Sambuc 	return r;
162*433d6423SLionel Sambuc   }
163*433d6423SLionel Sambuc 
164*433d6423SLionel Sambuc   key_name[DS_MAX_KEYLEN-1] = '\0';
165*433d6423SLionel Sambuc 
166*433d6423SLionel Sambuc   return OK;
167*433d6423SLionel Sambuc }
168*433d6423SLionel Sambuc 
169*433d6423SLionel Sambuc /*===========================================================================*
170*433d6423SLionel Sambuc  *				check_sub_match				     *
171*433d6423SLionel Sambuc  *===========================================================================*/
172*433d6423SLionel Sambuc static int check_sub_match(const struct subscription *subp,
173*433d6423SLionel Sambuc 		struct data_store *dsp, endpoint_t ep)
174*433d6423SLionel Sambuc {
175*433d6423SLionel Sambuc /* Check if an entry matches a subscription. Return 1 in case of match. */
176*433d6423SLionel Sambuc   return (check_auth(dsp, ep, DSF_PRIV_SUBSCRIBE)
177*433d6423SLionel Sambuc 	  && regexec(&subp->regex, dsp->key, 0, NULL, 0) == 0)
178*433d6423SLionel Sambuc 	  ? 1 : 0;
179*433d6423SLionel Sambuc }
180*433d6423SLionel Sambuc 
181*433d6423SLionel Sambuc /*===========================================================================*
182*433d6423SLionel Sambuc  *			     update_subscribers				     *
183*433d6423SLionel Sambuc  *===========================================================================*/
184*433d6423SLionel Sambuc static void update_subscribers(struct data_store *dsp, int set)
185*433d6423SLionel Sambuc {
186*433d6423SLionel Sambuc /* If set = 1, set bit in the sub bitmap of any subscription matching the given
187*433d6423SLionel Sambuc  * entry, otherwise clear it. In both cases, notify the subscriber.
188*433d6423SLionel Sambuc  */
189*433d6423SLionel Sambuc 	int i;
190*433d6423SLionel Sambuc 	int nr = dsp - ds_store;
191*433d6423SLionel Sambuc 	endpoint_t ep;
192*433d6423SLionel Sambuc 
193*433d6423SLionel Sambuc 	for(i = 0; i < NR_DS_SUBS; i++) {
194*433d6423SLionel Sambuc 		if(!(ds_subs[i].flags & DSF_IN_USE))
195*433d6423SLionel Sambuc 			continue;
196*433d6423SLionel Sambuc 		if(!(ds_subs[i].flags & dsp->flags & DSF_MASK_TYPE))
197*433d6423SLionel Sambuc 			continue;
198*433d6423SLionel Sambuc 
199*433d6423SLionel Sambuc 		ep = ds_getprocep(ds_subs[i].owner);
200*433d6423SLionel Sambuc 		if(!check_sub_match(&ds_subs[i], dsp, ep))
201*433d6423SLionel Sambuc 			continue;
202*433d6423SLionel Sambuc 
203*433d6423SLionel Sambuc 		if(set == 1) {
204*433d6423SLionel Sambuc 			SET_BIT(ds_subs[i].old_subs, nr);
205*433d6423SLionel Sambuc 		} else {
206*433d6423SLionel Sambuc 			UNSET_BIT(ds_subs[i].old_subs, nr);
207*433d6423SLionel Sambuc 		}
208*433d6423SLionel Sambuc 		ipc_notify(ep);
209*433d6423SLionel Sambuc 	}
210*433d6423SLionel Sambuc }
211*433d6423SLionel Sambuc 
212*433d6423SLionel Sambuc /*===========================================================================*
213*433d6423SLionel Sambuc  *		               map_service                                   *
214*433d6423SLionel Sambuc  *===========================================================================*/
215*433d6423SLionel Sambuc static int map_service(const struct rprocpub *rpub)
216*433d6423SLionel Sambuc {
217*433d6423SLionel Sambuc /* Map a new service by registering its label. */
218*433d6423SLionel Sambuc   struct data_store *dsp;
219*433d6423SLionel Sambuc 
220*433d6423SLionel Sambuc   /* Allocate a new data slot. */
221*433d6423SLionel Sambuc   if((dsp = alloc_data_slot()) == NULL) {
222*433d6423SLionel Sambuc 	return ENOMEM;
223*433d6423SLionel Sambuc   }
224*433d6423SLionel Sambuc 
225*433d6423SLionel Sambuc   /* Set attributes. */
226*433d6423SLionel Sambuc   strcpy(dsp->key, rpub->label);
227*433d6423SLionel Sambuc   dsp->u.u32 = (u32_t) rpub->endpoint;
228*433d6423SLionel Sambuc   strcpy(dsp->owner, "rs");
229*433d6423SLionel Sambuc   dsp->flags = DSF_IN_USE | DSF_TYPE_LABEL;
230*433d6423SLionel Sambuc 
231*433d6423SLionel Sambuc   /* Update subscribers having a matching subscription. */
232*433d6423SLionel Sambuc   update_subscribers(dsp, 1);
233*433d6423SLionel Sambuc 
234*433d6423SLionel Sambuc   return(OK);
235*433d6423SLionel Sambuc }
236*433d6423SLionel Sambuc 
237*433d6423SLionel Sambuc /*===========================================================================*
238*433d6423SLionel Sambuc  *		            sef_cb_init_fresh                                *
239*433d6423SLionel Sambuc  *===========================================================================*/
240*433d6423SLionel Sambuc int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
241*433d6423SLionel Sambuc {
242*433d6423SLionel Sambuc /* Initialize the data store server. */
243*433d6423SLionel Sambuc 	int i, r;
244*433d6423SLionel Sambuc 	struct rprocpub rprocpub[NR_BOOT_PROCS];
245*433d6423SLionel Sambuc 
246*433d6423SLionel Sambuc 	/* Reset data store: data and subscriptions. */
247*433d6423SLionel Sambuc 	for(i = 0; i < NR_DS_KEYS; i++) {
248*433d6423SLionel Sambuc 		ds_store[i].flags = 0;
249*433d6423SLionel Sambuc 	}
250*433d6423SLionel Sambuc 	for(i = 0; i < NR_DS_SUBS; i++) {
251*433d6423SLionel Sambuc 		ds_subs[i].flags = 0;
252*433d6423SLionel Sambuc 	}
253*433d6423SLionel Sambuc 
254*433d6423SLionel Sambuc 	/* Map all the services in the boot image. */
255*433d6423SLionel Sambuc 	if((r = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
256*433d6423SLionel Sambuc 		(vir_bytes) rprocpub, sizeof(rprocpub))) != OK) {
257*433d6423SLionel Sambuc 		panic("sys_safecopyfrom failed: %d", r);
258*433d6423SLionel Sambuc 	}
259*433d6423SLionel Sambuc 	for(i=0;i < NR_BOOT_PROCS;i++) {
260*433d6423SLionel Sambuc 		if(rprocpub[i].in_use) {
261*433d6423SLionel Sambuc 			if((r = map_service(&rprocpub[i])) != OK) {
262*433d6423SLionel Sambuc 				panic("unable to map service: %d", r);
263*433d6423SLionel Sambuc 			}
264*433d6423SLionel Sambuc 		}
265*433d6423SLionel Sambuc 	}
266*433d6423SLionel Sambuc 
267*433d6423SLionel Sambuc 	return(OK);
268*433d6423SLionel Sambuc }
269*433d6423SLionel Sambuc 
270*433d6423SLionel Sambuc /*===========================================================================*
271*433d6423SLionel Sambuc  *				do_publish				     *
272*433d6423SLionel Sambuc  *===========================================================================*/
273*433d6423SLionel Sambuc int do_publish(message *m_ptr)
274*433d6423SLionel Sambuc {
275*433d6423SLionel Sambuc   struct data_store *dsp;
276*433d6423SLionel Sambuc   char key_name[DS_MAX_KEYLEN];
277*433d6423SLionel Sambuc   char *source;
278*433d6423SLionel Sambuc   int flags = m_ptr->m_ds_req.flags;
279*433d6423SLionel Sambuc   size_t length;
280*433d6423SLionel Sambuc   int r;
281*433d6423SLionel Sambuc 
282*433d6423SLionel Sambuc   /* Lookup the source. */
283*433d6423SLionel Sambuc   source = ds_getprocname(m_ptr->m_source);
284*433d6423SLionel Sambuc   if(source == NULL)
285*433d6423SLionel Sambuc 	  return EPERM;
286*433d6423SLionel Sambuc 
287*433d6423SLionel Sambuc   /* Only RS can publish labels. */
288*433d6423SLionel Sambuc   if((flags & DSF_TYPE_LABEL) && m_ptr->m_source != RS_PROC_NR)
289*433d6423SLionel Sambuc 	  return EPERM;
290*433d6423SLionel Sambuc 
291*433d6423SLionel Sambuc   /* Get key name. */
292*433d6423SLionel Sambuc   if((r = get_key_name(m_ptr, key_name)) != OK)
293*433d6423SLionel Sambuc 	return r;
294*433d6423SLionel Sambuc 
295*433d6423SLionel Sambuc   /* Lookup the entry. */
296*433d6423SLionel Sambuc   dsp = lookup_entry(key_name, flags & DSF_MASK_TYPE);
297*433d6423SLionel Sambuc   /* If type is LABEL, also try to lookup the entry by num. */
298*433d6423SLionel Sambuc   if((flags & DSF_TYPE_LABEL) && (dsp == NULL))
299*433d6423SLionel Sambuc 	dsp = lookup_label_entry(m_ptr->m_ds_req.val_in.ep);
300*433d6423SLionel Sambuc 
301*433d6423SLionel Sambuc   if(dsp == NULL) {
302*433d6423SLionel Sambuc 	/* The entry doesn't exist, allocate a new data slot. */
303*433d6423SLionel Sambuc 	if((dsp = alloc_data_slot()) == NULL)
304*433d6423SLionel Sambuc 		return ENOMEM;
305*433d6423SLionel Sambuc   } else if (flags & DSF_OVERWRITE) {
306*433d6423SLionel Sambuc 	/* Overwrite. */
307*433d6423SLionel Sambuc 	if(!check_auth(dsp, m_ptr->m_source, DSF_PRIV_OVERWRITE))
308*433d6423SLionel Sambuc 		return EPERM;
309*433d6423SLionel Sambuc   } else {
310*433d6423SLionel Sambuc 	/* Don't overwrite and return error. */
311*433d6423SLionel Sambuc 	return EEXIST;
312*433d6423SLionel Sambuc   }
313*433d6423SLionel Sambuc 
314*433d6423SLionel Sambuc   /* Store! */
315*433d6423SLionel Sambuc   switch(flags & DSF_MASK_TYPE) {
316*433d6423SLionel Sambuc   case DSF_TYPE_U32:
317*433d6423SLionel Sambuc 	dsp->u.u32 = m_ptr->m_ds_req.val_in.u32;
318*433d6423SLionel Sambuc 	break;
319*433d6423SLionel Sambuc   case DSF_TYPE_LABEL:
320*433d6423SLionel Sambuc 	dsp->u.u32 = m_ptr->m_ds_req.val_in.ep;
321*433d6423SLionel Sambuc 	break;
322*433d6423SLionel Sambuc   case DSF_TYPE_STR:
323*433d6423SLionel Sambuc   case DSF_TYPE_MEM:
324*433d6423SLionel Sambuc 	length = m_ptr->m_ds_req.val_len;
325*433d6423SLionel Sambuc 	/* Allocate a new data buffer if necessary. */
326*433d6423SLionel Sambuc 	if(!(dsp->flags & DSF_IN_USE)) {
327*433d6423SLionel Sambuc 		if((dsp->u.mem.data = malloc(length)) == NULL)
328*433d6423SLionel Sambuc 			return ENOMEM;
329*433d6423SLionel Sambuc 		dsp->u.mem.reallen = length;
330*433d6423SLionel Sambuc 	} else if(length > dsp->u.mem.reallen) {
331*433d6423SLionel Sambuc 		free(dsp->u.mem.data);
332*433d6423SLionel Sambuc 		if((dsp->u.mem.data = malloc(length)) == NULL)
333*433d6423SLionel Sambuc 			return ENOMEM;
334*433d6423SLionel Sambuc 		dsp->u.mem.reallen = length;
335*433d6423SLionel Sambuc 	}
336*433d6423SLionel Sambuc 
337*433d6423SLionel Sambuc 	/* Copy the memory range. */
338*433d6423SLionel Sambuc 	r = sys_safecopyfrom(m_ptr->m_source, m_ptr->m_ds_req.val_in.grant,
339*433d6423SLionel Sambuc 	        0, (vir_bytes) dsp->u.mem.data, length);
340*433d6423SLionel Sambuc 	if(r != OK) {
341*433d6423SLionel Sambuc 		printf("DS: publish: memory map/copy failed from %d: %d\n",
342*433d6423SLionel Sambuc 			m_ptr->m_source, r);
343*433d6423SLionel Sambuc 		free(dsp->u.mem.data);
344*433d6423SLionel Sambuc 		return r;
345*433d6423SLionel Sambuc 	}
346*433d6423SLionel Sambuc 	dsp->u.mem.length = length;
347*433d6423SLionel Sambuc 	if(flags & DSF_TYPE_STR) {
348*433d6423SLionel Sambuc 		((char*)dsp->u.mem.data)[length-1] = '\0';
349*433d6423SLionel Sambuc 	}
350*433d6423SLionel Sambuc 	break;
351*433d6423SLionel Sambuc   default:
352*433d6423SLionel Sambuc 	return EINVAL;
353*433d6423SLionel Sambuc   }
354*433d6423SLionel Sambuc 
355*433d6423SLionel Sambuc   /* Set attributes. */
356*433d6423SLionel Sambuc   strcpy(dsp->key, key_name);
357*433d6423SLionel Sambuc   strcpy(dsp->owner, source);
358*433d6423SLionel Sambuc   dsp->flags = DSF_IN_USE | (flags & DSF_MASK_INTERNAL);
359*433d6423SLionel Sambuc 
360*433d6423SLionel Sambuc   /* Update subscribers having a matching subscription. */
361*433d6423SLionel Sambuc   update_subscribers(dsp, 1);
362*433d6423SLionel Sambuc 
363*433d6423SLionel Sambuc   return(OK);
364*433d6423SLionel Sambuc }
365*433d6423SLionel Sambuc 
366*433d6423SLionel Sambuc /*===========================================================================*
367*433d6423SLionel Sambuc  *				do_retrieve				     *
368*433d6423SLionel Sambuc  *===========================================================================*/
369*433d6423SLionel Sambuc int do_retrieve(message *m_ptr)
370*433d6423SLionel Sambuc {
371*433d6423SLionel Sambuc   struct data_store *dsp;
372*433d6423SLionel Sambuc   char key_name[DS_MAX_KEYLEN];
373*433d6423SLionel Sambuc   int flags = m_ptr->m_ds_req.flags;
374*433d6423SLionel Sambuc   int type = flags & DSF_MASK_TYPE;
375*433d6423SLionel Sambuc   size_t length;
376*433d6423SLionel Sambuc   int r;
377*433d6423SLionel Sambuc 
378*433d6423SLionel Sambuc   /* Get key name. */
379*433d6423SLionel Sambuc   if((r = get_key_name(m_ptr, key_name)) != OK)
380*433d6423SLionel Sambuc 	return r;
381*433d6423SLionel Sambuc 
382*433d6423SLionel Sambuc   /* Lookup the entry. */
383*433d6423SLionel Sambuc   if((dsp = lookup_entry(key_name, type)) == NULL)
384*433d6423SLionel Sambuc 	return ESRCH;
385*433d6423SLionel Sambuc   if(!check_auth(dsp, m_ptr->m_source, DSF_PRIV_RETRIEVE))
386*433d6423SLionel Sambuc 	return EPERM;
387*433d6423SLionel Sambuc 
388*433d6423SLionel Sambuc   /* Copy the requested data. */
389*433d6423SLionel Sambuc   switch(type) {
390*433d6423SLionel Sambuc   case DSF_TYPE_U32:
391*433d6423SLionel Sambuc 	m_ptr->m_ds_reply.val_out.u32 = dsp->u.u32;
392*433d6423SLionel Sambuc 	break;
393*433d6423SLionel Sambuc   case DSF_TYPE_LABEL:
394*433d6423SLionel Sambuc 	m_ptr->m_ds_reply.val_out.ep = dsp->u.u32;
395*433d6423SLionel Sambuc 	break;
396*433d6423SLionel Sambuc   case DSF_TYPE_STR:
397*433d6423SLionel Sambuc   case DSF_TYPE_MEM:
398*433d6423SLionel Sambuc 	length = MIN(m_ptr->m_ds_req.val_len, dsp->u.mem.length);
399*433d6423SLionel Sambuc 	r = sys_safecopyto(m_ptr->m_source, m_ptr->m_ds_req.val_in.grant, 0,
400*433d6423SLionel Sambuc 		(vir_bytes) dsp->u.mem.data, length);
401*433d6423SLionel Sambuc 	if(r != OK) {
402*433d6423SLionel Sambuc 		printf("DS: retrieve: copy failed to %d: %d\n",
403*433d6423SLionel Sambuc 			m_ptr->m_source, r);
404*433d6423SLionel Sambuc 		return r;
405*433d6423SLionel Sambuc 	}
406*433d6423SLionel Sambuc 	m_ptr->m_ds_reply.val_len = length;
407*433d6423SLionel Sambuc 	break;
408*433d6423SLionel Sambuc   default:
409*433d6423SLionel Sambuc 	return EINVAL;
410*433d6423SLionel Sambuc   }
411*433d6423SLionel Sambuc 
412*433d6423SLionel Sambuc   return OK;
413*433d6423SLionel Sambuc }
414*433d6423SLionel Sambuc 
415*433d6423SLionel Sambuc /*===========================================================================*
416*433d6423SLionel Sambuc  *				do_retrieve_label			     *
417*433d6423SLionel Sambuc  *===========================================================================*/
418*433d6423SLionel Sambuc int do_retrieve_label(const message *m_ptr)
419*433d6423SLionel Sambuc {
420*433d6423SLionel Sambuc   struct data_store *dsp;
421*433d6423SLionel Sambuc   int r;
422*433d6423SLionel Sambuc 
423*433d6423SLionel Sambuc   /* Lookup the label entry. */
424*433d6423SLionel Sambuc   if((dsp = lookup_label_entry(m_ptr->m_ds_req.val_in.ep)) == NULL)
425*433d6423SLionel Sambuc 	return ESRCH;
426*433d6423SLionel Sambuc 
427*433d6423SLionel Sambuc   /* Copy the key name. */
428*433d6423SLionel Sambuc   r = sys_safecopyto(m_ptr->m_source,
429*433d6423SLionel Sambuc 	(cp_grant_id_t) m_ptr->m_ds_req.key_grant, (vir_bytes) 0,
430*433d6423SLionel Sambuc 	(vir_bytes) dsp->key, strlen(dsp->key) + 1);
431*433d6423SLionel Sambuc   if(r != OK) {
432*433d6423SLionel Sambuc 	printf("DS: copy failed from %d: %d\n", m_ptr->m_source, r);
433*433d6423SLionel Sambuc 	return r;
434*433d6423SLionel Sambuc   }
435*433d6423SLionel Sambuc 
436*433d6423SLionel Sambuc   return OK;
437*433d6423SLionel Sambuc }
438*433d6423SLionel Sambuc 
439*433d6423SLionel Sambuc /*===========================================================================*
440*433d6423SLionel Sambuc  *				do_subscribe				     *
441*433d6423SLionel Sambuc  *===========================================================================*/
442*433d6423SLionel Sambuc int do_subscribe(message *m_ptr)
443*433d6423SLionel Sambuc {
444*433d6423SLionel Sambuc   char regex[DS_MAX_KEYLEN+2];
445*433d6423SLionel Sambuc   struct subscription *subp;
446*433d6423SLionel Sambuc   char errbuf[80];
447*433d6423SLionel Sambuc   char *owner;
448*433d6423SLionel Sambuc   int type_set;
449*433d6423SLionel Sambuc   int r, e, b;
450*433d6423SLionel Sambuc 
451*433d6423SLionel Sambuc   /* Find the owner. */
452*433d6423SLionel Sambuc   owner = ds_getprocname(m_ptr->m_source);
453*433d6423SLionel Sambuc   if(owner == NULL)
454*433d6423SLionel Sambuc 	  return ESRCH;
455*433d6423SLionel Sambuc 
456*433d6423SLionel Sambuc   /* See if the owner already has an existing subscription. */
457*433d6423SLionel Sambuc   if((subp = lookup_sub(owner)) == NULL) {
458*433d6423SLionel Sambuc 	/* The subscription doesn't exist, allocate a new one. */
459*433d6423SLionel Sambuc 	if((subp = alloc_sub_slot()) == NULL)
460*433d6423SLionel Sambuc 		return EAGAIN;
461*433d6423SLionel Sambuc   } else if(!(m_ptr->m_ds_req.flags & DSF_OVERWRITE)) {
462*433d6423SLionel Sambuc 	/* The subscription exists but we can't overwrite, return error. */
463*433d6423SLionel Sambuc 	return EEXIST;
464*433d6423SLionel Sambuc   }
465*433d6423SLionel Sambuc 
466*433d6423SLionel Sambuc   /* Copy key name from the caller. Anchor the subscription with "^regexp$" so
467*433d6423SLionel Sambuc    * substrings don't match. The caller will probably not expect this,
468*433d6423SLionel Sambuc    * and the usual case is for a complete match.
469*433d6423SLionel Sambuc    */
470*433d6423SLionel Sambuc   regex[0] = '^';
471*433d6423SLionel Sambuc   if((r = get_key_name(m_ptr, regex+1)) != OK)
472*433d6423SLionel Sambuc 	return r;
473*433d6423SLionel Sambuc   strcat(regex, "$");
474*433d6423SLionel Sambuc 
475*433d6423SLionel Sambuc   /* Compile regular expression. */
476*433d6423SLionel Sambuc   if((e=regcomp(&subp->regex, regex, REG_EXTENDED)) != 0) {
477*433d6423SLionel Sambuc 	regerror(e, &subp->regex, errbuf, sizeof(errbuf));
478*433d6423SLionel Sambuc 	printf("DS: subscribe: regerror: %s\n", errbuf);
479*433d6423SLionel Sambuc 	return EINVAL;
480*433d6423SLionel Sambuc   }
481*433d6423SLionel Sambuc 
482*433d6423SLionel Sambuc   /* If type_set = 0, then subscribe all types. */
483*433d6423SLionel Sambuc   type_set = m_ptr->m_ds_req.flags & DSF_MASK_TYPE;
484*433d6423SLionel Sambuc   if(type_set == 0)
485*433d6423SLionel Sambuc 	  type_set = DSF_MASK_TYPE;
486*433d6423SLionel Sambuc 
487*433d6423SLionel Sambuc   subp->flags = DSF_IN_USE | type_set;
488*433d6423SLionel Sambuc   strcpy(subp->owner, owner);
489*433d6423SLionel Sambuc   for(b = 0; b < BITMAP_CHUNKS(NR_DS_KEYS); b++)
490*433d6423SLionel Sambuc 	subp->old_subs[b] = 0;
491*433d6423SLionel Sambuc 
492*433d6423SLionel Sambuc   /* See if caller requested an instant initial list. */
493*433d6423SLionel Sambuc   if(m_ptr->m_ds_req.flags & DSF_INITIAL) {
494*433d6423SLionel Sambuc 	int i, match_found = FALSE;
495*433d6423SLionel Sambuc 	for(i = 0; i < NR_DS_KEYS; i++) {
496*433d6423SLionel Sambuc 		if(!(ds_store[i].flags & DSF_IN_USE))
497*433d6423SLionel Sambuc 			continue;
498*433d6423SLionel Sambuc 		if(!(ds_store[i].flags & type_set))
499*433d6423SLionel Sambuc 			continue;
500*433d6423SLionel Sambuc 		if(!check_sub_match(subp, &ds_store[i], m_ptr->m_source))
501*433d6423SLionel Sambuc 			continue;
502*433d6423SLionel Sambuc 
503*433d6423SLionel Sambuc 		SET_BIT(subp->old_subs, i);
504*433d6423SLionel Sambuc 		match_found = TRUE;
505*433d6423SLionel Sambuc 	}
506*433d6423SLionel Sambuc 
507*433d6423SLionel Sambuc 	/* Notify in case of match. */
508*433d6423SLionel Sambuc 	if(match_found)
509*433d6423SLionel Sambuc 		ipc_notify(m_ptr->m_source);
510*433d6423SLionel Sambuc   }
511*433d6423SLionel Sambuc 
512*433d6423SLionel Sambuc   return OK;
513*433d6423SLionel Sambuc }
514*433d6423SLionel Sambuc 
515*433d6423SLionel Sambuc /*===========================================================================*
516*433d6423SLionel Sambuc  *				do_check				     *
517*433d6423SLionel Sambuc  *===========================================================================*/
518*433d6423SLionel Sambuc int do_check(message *m_ptr)
519*433d6423SLionel Sambuc {
520*433d6423SLionel Sambuc   struct subscription *subp;
521*433d6423SLionel Sambuc   char *owner;
522*433d6423SLionel Sambuc   endpoint_t entry_owner_e;
523*433d6423SLionel Sambuc   int r, i;
524*433d6423SLionel Sambuc 
525*433d6423SLionel Sambuc   /* Find the subscription owner. */
526*433d6423SLionel Sambuc   owner = ds_getprocname(m_ptr->m_source);
527*433d6423SLionel Sambuc   if(owner == NULL)
528*433d6423SLionel Sambuc 	  return ESRCH;
529*433d6423SLionel Sambuc 
530*433d6423SLionel Sambuc   /* Lookup the owner's subscription. */
531*433d6423SLionel Sambuc   if((subp = lookup_sub(owner)) == NULL)
532*433d6423SLionel Sambuc 	return ESRCH;
533*433d6423SLionel Sambuc 
534*433d6423SLionel Sambuc   /* Look for an updated entry the subscriber is interested in. */
535*433d6423SLionel Sambuc   for(i = 0; i < NR_DS_KEYS; i++) {
536*433d6423SLionel Sambuc 	if(GET_BIT(subp->old_subs, i))
537*433d6423SLionel Sambuc 		break;
538*433d6423SLionel Sambuc   }
539*433d6423SLionel Sambuc   if(i == NR_DS_KEYS)
540*433d6423SLionel Sambuc 	return ENOENT;
541*433d6423SLionel Sambuc 
542*433d6423SLionel Sambuc   /* Copy the key name. */
543*433d6423SLionel Sambuc   r = sys_safecopyto(m_ptr->m_source,
544*433d6423SLionel Sambuc 	(cp_grant_id_t) m_ptr->m_ds_req.key_grant, (vir_bytes) 0,
545*433d6423SLionel Sambuc 	(vir_bytes) ds_store[i].key, strlen(ds_store[i].key) + 1);
546*433d6423SLionel Sambuc   if(r != OK) {
547*433d6423SLionel Sambuc 	printf("DS: check: copy failed from %d: %d\n", m_ptr->m_source, r);
548*433d6423SLionel Sambuc 	return r;
549*433d6423SLionel Sambuc   }
550*433d6423SLionel Sambuc 
551*433d6423SLionel Sambuc   /* Copy the type and the owner of the original entry. */
552*433d6423SLionel Sambuc   entry_owner_e = ds_getprocep(ds_store[i].owner);
553*433d6423SLionel Sambuc   m_ptr->m_ds_req.flags = ds_store[i].flags & DSF_MASK_TYPE;
554*433d6423SLionel Sambuc   m_ptr->m_ds_req.owner = entry_owner_e;
555*433d6423SLionel Sambuc 
556*433d6423SLionel Sambuc   /* Mark the entry as no longer updated for the subscriber. */
557*433d6423SLionel Sambuc   UNSET_BIT(subp->old_subs, i);
558*433d6423SLionel Sambuc 
559*433d6423SLionel Sambuc   return OK;
560*433d6423SLionel Sambuc }
561*433d6423SLionel Sambuc 
562*433d6423SLionel Sambuc /*===========================================================================*
563*433d6423SLionel Sambuc  *				do_delete				     *
564*433d6423SLionel Sambuc  *===========================================================================*/
565*433d6423SLionel Sambuc int do_delete(message *m_ptr)
566*433d6423SLionel Sambuc {
567*433d6423SLionel Sambuc   struct data_store *dsp;
568*433d6423SLionel Sambuc   char key_name[DS_MAX_KEYLEN];
569*433d6423SLionel Sambuc   char *source;
570*433d6423SLionel Sambuc   char *label;
571*433d6423SLionel Sambuc   int type = m_ptr->m_ds_req.flags & DSF_MASK_TYPE;
572*433d6423SLionel Sambuc   int i, r;
573*433d6423SLionel Sambuc 
574*433d6423SLionel Sambuc   /* Lookup the source. */
575*433d6423SLionel Sambuc   source = ds_getprocname(m_ptr->m_source);
576*433d6423SLionel Sambuc   if(source == NULL)
577*433d6423SLionel Sambuc 	  return EPERM;
578*433d6423SLionel Sambuc 
579*433d6423SLionel Sambuc   /* Get key name. */
580*433d6423SLionel Sambuc   if((r = get_key_name(m_ptr, key_name)) != OK)
581*433d6423SLionel Sambuc 	return r;
582*433d6423SLionel Sambuc 
583*433d6423SLionel Sambuc   /* Lookup the entry. */
584*433d6423SLionel Sambuc   if((dsp = lookup_entry(key_name, type)) == NULL)
585*433d6423SLionel Sambuc 	return ESRCH;
586*433d6423SLionel Sambuc 
587*433d6423SLionel Sambuc   /* Only the owner can delete. */
588*433d6423SLionel Sambuc   if(strcmp(dsp->owner, source))
589*433d6423SLionel Sambuc 	return EPERM;
590*433d6423SLionel Sambuc 
591*433d6423SLionel Sambuc   switch(type) {
592*433d6423SLionel Sambuc   case DSF_TYPE_U32:
593*433d6423SLionel Sambuc 	break;
594*433d6423SLionel Sambuc   case DSF_TYPE_LABEL:
595*433d6423SLionel Sambuc 	label = dsp->key;
596*433d6423SLionel Sambuc 
597*433d6423SLionel Sambuc 	/* Clean up subscriptions. */
598*433d6423SLionel Sambuc 	for (i = 0; i < NR_DS_SUBS; i++) {
599*433d6423SLionel Sambuc 		if ((ds_subs[i].flags & DSF_IN_USE)
600*433d6423SLionel Sambuc 			&& !strcmp(ds_subs[i].owner, label)) {
601*433d6423SLionel Sambuc 			ds_subs[i].flags = 0;
602*433d6423SLionel Sambuc 		}
603*433d6423SLionel Sambuc 	}
604*433d6423SLionel Sambuc 
605*433d6423SLionel Sambuc 	/* Clean up data entries. */
606*433d6423SLionel Sambuc 	for (i = 0; i < NR_DS_KEYS; i++) {
607*433d6423SLionel Sambuc 		if ((ds_store[i].flags & DSF_IN_USE)
608*433d6423SLionel Sambuc 			&& !strcmp(ds_store[i].owner, label)) {
609*433d6423SLionel Sambuc 			update_subscribers(&ds_store[i], 0);
610*433d6423SLionel Sambuc 
611*433d6423SLionel Sambuc 			ds_store[i].flags = 0;
612*433d6423SLionel Sambuc 		}
613*433d6423SLionel Sambuc 	}
614*433d6423SLionel Sambuc 	break;
615*433d6423SLionel Sambuc   case DSF_TYPE_STR:
616*433d6423SLionel Sambuc   case DSF_TYPE_MEM:
617*433d6423SLionel Sambuc 	free(dsp->u.mem.data);
618*433d6423SLionel Sambuc 	break;
619*433d6423SLionel Sambuc   default:
620*433d6423SLionel Sambuc 	return EINVAL;
621*433d6423SLionel Sambuc   }
622*433d6423SLionel Sambuc 
623*433d6423SLionel Sambuc   /* Update subscribers having a matching subscription. */
624*433d6423SLionel Sambuc   update_subscribers(dsp, 0);
625*433d6423SLionel Sambuc 
626*433d6423SLionel Sambuc   /* Clear the entry. */
627*433d6423SLionel Sambuc   dsp->flags = 0;
628*433d6423SLionel Sambuc 
629*433d6423SLionel Sambuc   return OK;
630*433d6423SLionel Sambuc }
631*433d6423SLionel Sambuc 
632*433d6423SLionel Sambuc /*===========================================================================*
633*433d6423SLionel Sambuc  *				do_getsysinfo				     *
634*433d6423SLionel Sambuc  *===========================================================================*/
635*433d6423SLionel Sambuc int do_getsysinfo(const message *m_ptr)
636*433d6423SLionel Sambuc {
637*433d6423SLionel Sambuc   vir_bytes src_addr;
638*433d6423SLionel Sambuc   size_t length;
639*433d6423SLionel Sambuc   int s;
640*433d6423SLionel Sambuc 
641*433d6423SLionel Sambuc   switch(m_ptr->m_lsys_getsysinfo.what) {
642*433d6423SLionel Sambuc   case SI_DATA_STORE:
643*433d6423SLionel Sambuc 	src_addr = (vir_bytes)ds_store;
644*433d6423SLionel Sambuc 	length = sizeof(struct data_store) * NR_DS_KEYS;
645*433d6423SLionel Sambuc 	break;
646*433d6423SLionel Sambuc   default:
647*433d6423SLionel Sambuc   	return EINVAL;
648*433d6423SLionel Sambuc   }
649*433d6423SLionel Sambuc 
650*433d6423SLionel Sambuc   if (length != m_ptr->m_lsys_getsysinfo.size)
651*433d6423SLionel Sambuc 	return EINVAL;
652*433d6423SLionel Sambuc 
653*433d6423SLionel Sambuc   if (OK != (s=sys_datacopy(SELF, src_addr,
654*433d6423SLionel Sambuc 		m_ptr->m_source, m_ptr->m_lsys_getsysinfo.where, length))) {
655*433d6423SLionel Sambuc 	printf("DS: copy failed: %d\n", s);
656*433d6423SLionel Sambuc 	return s;
657*433d6423SLionel Sambuc   }
658*433d6423SLionel Sambuc 
659*433d6423SLionel Sambuc   return OK;
660*433d6423SLionel Sambuc }
661*433d6423SLionel Sambuc 
662