4 /* Allocate space for the data store. */
5 static struct data_store ds_store
[NR_DS_KEYS
];
6 static struct subscription ds_subs
[NR_DS_SUBS
];
8 /*===========================================================================*
10 *===========================================================================*/
11 static struct data_store
*alloc_data_slot(void)
13 /* Allocate a new data slot. */
16 for (i
= 0; i
< NR_DS_KEYS
; i
++) {
17 if (!(ds_store
[i
].flags
& DSF_IN_USE
))
24 /*===========================================================================*
26 *===========================================================================*/
27 static struct subscription
*alloc_sub_slot(void)
29 /* Return a free subscription slot. */
32 for (i
= 0; i
< NR_DS_SUBS
; i
++) {
33 if (!(ds_subs
[i
].flags
& DSF_IN_USE
))
40 /*===========================================================================*
42 *===========================================================================*/
43 static void free_sub_slot(struct subscription
*subp
)
45 /* Clean up a previously successfully) allocated subscription slot. */
46 assert(subp
->flags
& DSF_IN_USE
);
48 regfree(&subp
->regex
);
49 memset(&subp
->regex
, 0, sizeof(subp
->regex
));
54 /*===========================================================================*
56 *===========================================================================*/
57 static struct data_store
*lookup_entry(const char *key_name
, int type
)
59 /* Lookup an existing entry by key and type. */
62 for (i
= 0; i
< NR_DS_KEYS
; i
++) {
63 if ((ds_store
[i
].flags
& DSF_IN_USE
) /* used */
64 && (ds_store
[i
].flags
& type
) /* same type*/
65 && !strcmp(ds_store
[i
].key
, key_name
)) /* same key*/
72 /*===========================================================================*
73 * lookup_label_entry *
74 *===========================================================================*/
75 static struct data_store
*lookup_label_entry(unsigned num
)
77 /* Lookup an existing label entry by num. */
80 for (i
= 0; i
< NR_DS_KEYS
; i
++) {
81 if ((ds_store
[i
].flags
& DSF_IN_USE
)
82 && (ds_store
[i
].flags
& DSF_TYPE_LABEL
)
83 && (ds_store
[i
].u
.u32
== num
))
90 /*===========================================================================*
92 *===========================================================================*/
93 static struct subscription
*lookup_sub(const char *owner
)
95 /* Lookup an existing subscription given its owner. */
98 for (i
= 0; i
< NR_DS_SUBS
; i
++) {
99 if ((ds_subs
[i
].flags
& DSF_IN_USE
) /* used */
100 && !strcmp(ds_subs
[i
].owner
, owner
)) /* same key*/
107 /*===========================================================================*
109 *===========================================================================*/
110 static char *ds_getprocname(endpoint_t e
)
112 /* Get a process name given its endpoint. */
113 struct data_store
*dsp
;
115 static char *first_proc_name
= "ds";
116 endpoint_t first_proc_ep
= DS_PROC_NR
;
118 if(e
== first_proc_ep
)
119 return first_proc_name
;
121 if((dsp
= lookup_label_entry(e
)) != NULL
)
127 /*===========================================================================*
129 *===========================================================================*/
130 static endpoint_t
ds_getprocep(const char *s
)
132 /* Get a process endpoint given its name. */
133 struct data_store
*dsp
;
135 if((dsp
= lookup_entry(s
, DSF_TYPE_LABEL
)) != NULL
)
137 panic("ds_getprocep: process endpoint not found");
140 /*===========================================================================*
142 *===========================================================================*/
143 static int check_auth(const struct data_store
*p
, endpoint_t ep
, int perm
)
145 /* Check authorization for a given type of permission. */
148 if(!(p
->flags
& perm
))
151 source
= ds_getprocname(ep
);
152 return source
&& !strcmp(p
->owner
, source
);
155 /*===========================================================================*
157 *===========================================================================*/
158 static int get_key_name(const message
*m_ptr
, char *key_name
)
160 /* Get key name given an input message. */
163 if (m_ptr
->m_ds_req
.key_len
> DS_MAX_KEYLEN
|| m_ptr
->m_ds_req
.key_len
< 2) {
164 printf("DS: bogus key length (%d) from %d\n", m_ptr
->m_ds_req
.key_len
,
169 /* Copy name from caller. */
170 r
= sys_safecopyfrom(m_ptr
->m_source
,
171 (cp_grant_id_t
) m_ptr
->m_ds_req
.key_grant
, 0,
172 (vir_bytes
) key_name
, m_ptr
->m_ds_req
.key_len
);
174 printf("DS: publish: copy failed from %d: %d\n", m_ptr
->m_source
, r
);
178 key_name
[DS_MAX_KEYLEN
-1] = '\0';
183 /*===========================================================================*
185 *===========================================================================*/
186 static int check_sub_match(const struct subscription
*subp
,
187 struct data_store
*dsp
, endpoint_t ep
)
189 /* Check if an entry matches a subscription. Return 1 in case of match. */
190 return (check_auth(dsp
, ep
, DSF_PRIV_SUBSCRIBE
)
191 && regexec(&subp
->regex
, dsp
->key
, 0, NULL
, 0) == 0)
195 /*===========================================================================*
196 * update_subscribers *
197 *===========================================================================*/
198 static void update_subscribers(struct data_store
*dsp
, int set
)
200 /* If set = 1, set bit in the sub bitmap of any subscription matching the given
201 * entry, otherwise clear it. In both cases, notify the subscriber.
204 int nr
= dsp
- ds_store
;
207 for(i
= 0; i
< NR_DS_SUBS
; i
++) {
208 if(!(ds_subs
[i
].flags
& DSF_IN_USE
))
210 if(!(ds_subs
[i
].flags
& dsp
->flags
& DSF_MASK_TYPE
))
213 ep
= ds_getprocep(ds_subs
[i
].owner
);
214 if(!check_sub_match(&ds_subs
[i
], dsp
, ep
))
218 SET_BIT(ds_subs
[i
].old_subs
, nr
);
220 UNSET_BIT(ds_subs
[i
].old_subs
, nr
);
226 /*===========================================================================*
228 *===========================================================================*/
229 static int map_service(const struct rprocpub
*rpub
)
231 /* Map a new service by registering its label. */
232 struct data_store
*dsp
;
234 /* Allocate a new data slot. */
235 if((dsp
= alloc_data_slot()) == NULL
) {
239 /* Set attributes. */
240 strcpy(dsp
->key
, rpub
->label
);
241 dsp
->u
.u32
= (u32_t
) rpub
->endpoint
;
242 strcpy(dsp
->owner
, "rs");
243 dsp
->flags
= DSF_IN_USE
| DSF_TYPE_LABEL
;
245 /* Update subscribers having a matching subscription. */
246 update_subscribers(dsp
, 1);
251 /*===========================================================================*
252 * sef_cb_init_fresh *
253 *===========================================================================*/
254 int sef_cb_init_fresh(int UNUSED(type
), sef_init_info_t
*info
)
256 /* Initialize the data store server. */
258 struct rprocpub rprocpub
[NR_BOOT_PROCS
];
260 /* Reset data store: data and subscriptions. */
261 for(i
= 0; i
< NR_DS_KEYS
; i
++) {
262 ds_store
[i
].flags
= 0;
264 for(i
= 0; i
< NR_DS_SUBS
; i
++) {
265 ds_subs
[i
].flags
= 0;
268 /* Map all the services in the boot image. */
269 if((r
= sys_safecopyfrom(RS_PROC_NR
, info
->rproctab_gid
, 0,
270 (vir_bytes
) rprocpub
, sizeof(rprocpub
))) != OK
) {
271 panic("sys_safecopyfrom failed: %d", r
);
273 for(i
=0;i
< NR_BOOT_PROCS
;i
++) {
274 if(rprocpub
[i
].in_use
) {
275 if((r
= map_service(&rprocpub
[i
])) != OK
) {
276 panic("unable to map service: %d", r
);
284 /*===========================================================================*
286 *===========================================================================*/
287 int do_publish(message
*m_ptr
)
289 struct data_store
*dsp
;
290 char key_name
[DS_MAX_KEYLEN
];
292 int flags
= m_ptr
->m_ds_req
.flags
;
296 /* Lookup the source. */
297 source
= ds_getprocname(m_ptr
->m_source
);
301 /* Only RS can publish labels. */
302 if((flags
& DSF_TYPE_LABEL
) && m_ptr
->m_source
!= RS_PROC_NR
)
306 if((r
= get_key_name(m_ptr
, key_name
)) != OK
)
309 /* Lookup the entry. */
310 dsp
= lookup_entry(key_name
, flags
& DSF_MASK_TYPE
);
311 /* If type is LABEL, also try to lookup the entry by num. */
312 if((flags
& DSF_TYPE_LABEL
) && (dsp
== NULL
))
313 dsp
= lookup_label_entry(m_ptr
->m_ds_req
.val_in
.ep
);
316 /* The entry doesn't exist, allocate a new data slot. */
317 if((dsp
= alloc_data_slot()) == NULL
)
319 } else if (flags
& DSF_OVERWRITE
) {
321 if(!check_auth(dsp
, m_ptr
->m_source
, DSF_PRIV_OVERWRITE
))
324 /* Don't overwrite and return error. */
329 switch(flags
& DSF_MASK_TYPE
) {
331 dsp
->u
.u32
= m_ptr
->m_ds_req
.val_in
.u32
;
334 dsp
->u
.u32
= m_ptr
->m_ds_req
.val_in
.ep
;
338 length
= m_ptr
->m_ds_req
.val_len
;
339 /* Allocate a new data buffer if necessary. */
340 if(!(dsp
->flags
& DSF_IN_USE
)) {
341 if((dsp
->u
.mem
.data
= malloc(length
)) == NULL
)
343 dsp
->u
.mem
.reallen
= length
;
344 } else if(length
> dsp
->u
.mem
.reallen
) {
345 free(dsp
->u
.mem
.data
);
346 if((dsp
->u
.mem
.data
= malloc(length
)) == NULL
)
348 dsp
->u
.mem
.reallen
= length
;
351 /* Copy the memory range. */
352 r
= sys_safecopyfrom(m_ptr
->m_source
, m_ptr
->m_ds_req
.val_in
.grant
,
353 0, (vir_bytes
) dsp
->u
.mem
.data
, length
);
355 printf("DS: publish: memory map/copy failed from %d: %d\n",
357 free(dsp
->u
.mem
.data
);
360 dsp
->u
.mem
.length
= length
;
361 if(flags
& DSF_TYPE_STR
) {
362 ((char*)dsp
->u
.mem
.data
)[length
-1] = '\0';
369 /* Set attributes. */
370 strcpy(dsp
->key
, key_name
);
371 strcpy(dsp
->owner
, source
);
372 dsp
->flags
= DSF_IN_USE
| (flags
& DSF_MASK_INTERNAL
);
374 /* Update subscribers having a matching subscription. */
375 update_subscribers(dsp
, 1);
380 /*===========================================================================*
382 *===========================================================================*/
383 int do_retrieve(message
*m_ptr
)
385 struct data_store
*dsp
;
386 char key_name
[DS_MAX_KEYLEN
];
387 int flags
= m_ptr
->m_ds_req
.flags
;
388 int type
= flags
& DSF_MASK_TYPE
;
393 if((r
= get_key_name(m_ptr
, key_name
)) != OK
)
396 /* Lookup the entry. */
397 if((dsp
= lookup_entry(key_name
, type
)) == NULL
)
399 if(!check_auth(dsp
, m_ptr
->m_source
, DSF_PRIV_RETRIEVE
))
402 /* Copy the requested data. */
405 m_ptr
->m_ds_reply
.val_out
.u32
= dsp
->u
.u32
;
408 m_ptr
->m_ds_reply
.val_out
.ep
= dsp
->u
.u32
;
412 length
= MIN(m_ptr
->m_ds_req
.val_len
, dsp
->u
.mem
.length
);
413 r
= sys_safecopyto(m_ptr
->m_source
, m_ptr
->m_ds_req
.val_in
.grant
, 0,
414 (vir_bytes
) dsp
->u
.mem
.data
, length
);
416 printf("DS: retrieve: copy failed to %d: %d\n",
420 m_ptr
->m_ds_reply
.val_len
= length
;
429 /*===========================================================================*
430 * do_retrieve_label *
431 *===========================================================================*/
432 int do_retrieve_label(const message
*m_ptr
)
434 struct data_store
*dsp
;
437 /* Lookup the label entry. */
438 if((dsp
= lookup_label_entry(m_ptr
->m_ds_req
.val_in
.ep
)) == NULL
)
441 /* Copy the key name. */
442 r
= sys_safecopyto(m_ptr
->m_source
,
443 (cp_grant_id_t
) m_ptr
->m_ds_req
.key_grant
, (vir_bytes
) 0,
444 (vir_bytes
) dsp
->key
, strlen(dsp
->key
) + 1);
446 printf("DS: copy failed from %d: %d\n", m_ptr
->m_source
, r
);
453 /*===========================================================================*
455 *===========================================================================*/
456 int do_subscribe(message
*m_ptr
)
458 char regex
[DS_MAX_KEYLEN
+2];
459 struct subscription
*subp
;
465 /* Find the owner. */
466 owner
= ds_getprocname(m_ptr
->m_source
);
470 /* See if the owner already has an existing subscription. */
471 if ((subp
= lookup_sub(owner
)) != NULL
) {
472 /* If a subscription exists but we can't overwrite, return error. */
473 if (!(m_ptr
->m_ds_req
.flags
& DSF_OVERWRITE
))
475 /* Otherwise just free the old one. */
479 /* Find a free subscription slot. */
480 if ((subp
= alloc_sub_slot()) == NULL
)
483 /* Copy key name from the caller. Anchor the subscription with "^regexp$" so
484 * substrings don't match. The caller will probably not expect this,
485 * and the usual case is for a complete match.
488 if((r
= get_key_name(m_ptr
, regex
+1)) != OK
)
492 /* Compile regular expression. */
493 if((e
=regcomp(&subp
->regex
, regex
, REG_EXTENDED
)) != 0) {
494 regerror(e
, &subp
->regex
, errbuf
, sizeof(errbuf
));
495 printf("DS: subscribe: regerror: %s\n", errbuf
);
496 memset(&subp
->regex
, 0, sizeof(subp
->regex
));
500 /* If type_set = 0, then subscribe all types. */
501 type_set
= m_ptr
->m_ds_req
.flags
& DSF_MASK_TYPE
;
503 type_set
= DSF_MASK_TYPE
;
505 subp
->flags
= DSF_IN_USE
| type_set
;
506 strcpy(subp
->owner
, owner
);
507 for(b
= 0; b
< BITMAP_CHUNKS(NR_DS_KEYS
); b
++)
508 subp
->old_subs
[b
] = 0;
510 /* See if caller requested an instant initial list. */
511 if(m_ptr
->m_ds_req
.flags
& DSF_INITIAL
) {
512 int i
, match_found
= FALSE
;
513 for(i
= 0; i
< NR_DS_KEYS
; i
++) {
514 if(!(ds_store
[i
].flags
& DSF_IN_USE
))
516 if(!(ds_store
[i
].flags
& type_set
))
518 if(!check_sub_match(subp
, &ds_store
[i
], m_ptr
->m_source
))
521 SET_BIT(subp
->old_subs
, i
);
525 /* Notify in case of match. */
527 ipc_notify(m_ptr
->m_source
);
533 /*===========================================================================*
535 *===========================================================================*/
536 int do_check(message
*m_ptr
)
538 struct subscription
*subp
;
540 endpoint_t entry_owner_e
;
543 /* Find the subscription owner. */
544 owner
= ds_getprocname(m_ptr
->m_source
);
548 /* Lookup the owner's subscription. */
549 if((subp
= lookup_sub(owner
)) == NULL
)
552 /* Look for an updated entry the subscriber is interested in. */
553 for(i
= 0; i
< NR_DS_KEYS
; i
++) {
554 if(GET_BIT(subp
->old_subs
, i
))
560 /* Copy the key name. */
561 r
= sys_safecopyto(m_ptr
->m_source
,
562 (cp_grant_id_t
) m_ptr
->m_ds_req
.key_grant
, (vir_bytes
) 0,
563 (vir_bytes
) ds_store
[i
].key
, strlen(ds_store
[i
].key
) + 1);
565 printf("DS: check: copy failed from %d: %d\n", m_ptr
->m_source
, r
);
569 /* Copy the type and the owner of the original entry. */
570 entry_owner_e
= ds_getprocep(ds_store
[i
].owner
);
571 m_ptr
->m_ds_req
.flags
= ds_store
[i
].flags
& DSF_MASK_TYPE
;
572 m_ptr
->m_ds_req
.owner
= entry_owner_e
;
574 /* Mark the entry as no longer updated for the subscriber. */
575 UNSET_BIT(subp
->old_subs
, i
);
580 /*===========================================================================*
582 *===========================================================================*/
583 int do_delete(message
*m_ptr
)
585 struct data_store
*dsp
;
586 char key_name
[DS_MAX_KEYLEN
];
589 int type
= m_ptr
->m_ds_req
.flags
& DSF_MASK_TYPE
;
592 /* Lookup the source. */
593 source
= ds_getprocname(m_ptr
->m_source
);
598 if((r
= get_key_name(m_ptr
, key_name
)) != OK
)
601 /* Lookup the entry. */
602 if((dsp
= lookup_entry(key_name
, type
)) == NULL
)
605 /* Only the owner can delete. */
606 if(strcmp(dsp
->owner
, source
))
615 /* Clean up subscriptions. */
616 for (i
= 0; i
< NR_DS_SUBS
; i
++) {
617 if ((ds_subs
[i
].flags
& DSF_IN_USE
)
618 && !strcmp(ds_subs
[i
].owner
, label
)) {
619 free_sub_slot(&ds_subs
[i
]);
623 /* Clean up data entries. */
624 for (i
= 0; i
< NR_DS_KEYS
; i
++) {
625 if ((ds_store
[i
].flags
& DSF_IN_USE
)
626 && !strcmp(ds_store
[i
].owner
, label
)) {
627 update_subscribers(&ds_store
[i
], 0);
629 ds_store
[i
].flags
= 0;
635 free(dsp
->u
.mem
.data
);
641 /* Update subscribers having a matching subscription. */
642 update_subscribers(dsp
, 0);
644 /* Clear the entry. */
650 /*===========================================================================*
652 *===========================================================================*/
653 int do_getsysinfo(const message
*m_ptr
)
659 switch(m_ptr
->m_lsys_getsysinfo
.what
) {
661 src_addr
= (vir_bytes
)ds_store
;
662 length
= sizeof(struct data_store
) * NR_DS_KEYS
;
668 if (length
!= m_ptr
->m_lsys_getsysinfo
.size
)
671 if (OK
!= (s
=sys_datacopy(SELF
, src_addr
,
672 m_ptr
->m_source
, m_ptr
->m_lsys_getsysinfo
.where
, length
))) {
673 printf("DS: copy failed: %d\n", s
);