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 /* Allocate a new subscription slot. */
32 for (i
= 0; i
< NR_DS_SUBS
; i
++) {
33 if (!(ds_subs
[i
].flags
& DSF_IN_USE
))
40 /*===========================================================================*
42 *===========================================================================*/
43 static struct data_store
*lookup_entry(const char *key_name
, int type
)
45 /* Lookup an existing entry by key and type. */
48 for (i
= 0; i
< NR_DS_KEYS
; i
++) {
49 if ((ds_store
[i
].flags
& DSF_IN_USE
) /* used */
50 && (ds_store
[i
].flags
& type
) /* same type*/
51 && !strcmp(ds_store
[i
].key
, key_name
)) /* same key*/
58 /*===========================================================================*
59 * lookup_label_entry *
60 *===========================================================================*/
61 static struct data_store
*lookup_label_entry(unsigned num
)
63 /* Lookup an existing label entry by num. */
66 for (i
= 0; i
< NR_DS_KEYS
; i
++) {
67 if ((ds_store
[i
].flags
& DSF_IN_USE
)
68 && (ds_store
[i
].flags
& DSF_TYPE_LABEL
)
69 && (ds_store
[i
].u
.u32
== num
))
76 /*===========================================================================*
78 *===========================================================================*/
79 static struct subscription
*lookup_sub(const char *owner
)
81 /* Lookup an existing subscription given its owner. */
84 for (i
= 0; i
< NR_DS_SUBS
; i
++) {
85 if ((ds_subs
[i
].flags
& DSF_IN_USE
) /* used */
86 && !strcmp(ds_subs
[i
].owner
, owner
)) /* same key*/
93 /*===========================================================================*
95 *===========================================================================*/
96 static char *ds_getprocname(endpoint_t e
)
98 /* Get a process name given its endpoint. */
99 struct data_store
*dsp
;
101 static char *first_proc_name
= "ds";
102 endpoint_t first_proc_ep
= DS_PROC_NR
;
104 if(e
== first_proc_ep
)
105 return first_proc_name
;
107 if((dsp
= lookup_label_entry(e
)) != NULL
)
113 /*===========================================================================*
115 *===========================================================================*/
116 static endpoint_t
ds_getprocep(const char *s
)
118 /* Get a process endpoint given its name. */
119 struct data_store
*dsp
;
121 if((dsp
= lookup_entry(s
, DSF_TYPE_LABEL
)) != NULL
)
123 panic("ds_getprocep: process endpoint not found");
126 /*===========================================================================*
128 *===========================================================================*/
129 static int check_auth(const struct data_store
*p
, endpoint_t ep
, int perm
)
131 /* Check authorization for a given type of permission. */
134 if(!(p
->flags
& perm
))
137 source
= ds_getprocname(ep
);
138 return source
&& !strcmp(p
->owner
, source
);
141 /*===========================================================================*
143 *===========================================================================*/
144 static int get_key_name(const message
*m_ptr
, char *key_name
)
146 /* Get key name given an input message. */
149 if (m_ptr
->DS_KEY_LEN
> DS_MAX_KEYLEN
|| m_ptr
->DS_KEY_LEN
< 2) {
150 printf("DS: bogus key length (%d) from %d\n", m_ptr
->DS_KEY_LEN
,
155 /* Copy name from caller. */
156 r
= sys_safecopyfrom(m_ptr
->m_source
,
157 (cp_grant_id_t
) m_ptr
->DS_KEY_GRANT
, 0,
158 (vir_bytes
) key_name
, m_ptr
->DS_KEY_LEN
);
160 printf("DS: publish: copy failed from %d: %d\n", m_ptr
->m_source
, r
);
164 key_name
[DS_MAX_KEYLEN
-1] = '\0';
169 /*===========================================================================*
171 *===========================================================================*/
172 static int check_sub_match(const struct subscription
*subp
,
173 struct data_store
*dsp
, endpoint_t ep
)
175 /* Check if an entry matches a subscription. Return 1 in case of match. */
176 return (check_auth(dsp
, ep
, DSF_PRIV_SUBSCRIBE
)
177 && regexec(&subp
->regex
, dsp
->key
, 0, NULL
, 0) == 0)
181 /*===========================================================================*
182 * update_subscribers *
183 *===========================================================================*/
184 static void update_subscribers(struct data_store
*dsp
, int set
)
186 /* If set = 1, set bit in the sub bitmap of any subscription matching the given
187 * entry, otherwise clear it. In both cases, notify the subscriber.
190 int nr
= dsp
- ds_store
;
193 for(i
= 0; i
< NR_DS_SUBS
; i
++) {
194 if(!(ds_subs
[i
].flags
& DSF_IN_USE
))
196 if(!(ds_subs
[i
].flags
& dsp
->flags
& DSF_MASK_TYPE
))
199 ep
= ds_getprocep(ds_subs
[i
].owner
);
200 if(!check_sub_match(&ds_subs
[i
], dsp
, ep
))
204 SET_BIT(ds_subs
[i
].old_subs
, nr
);
206 UNSET_BIT(ds_subs
[i
].old_subs
, nr
);
212 /*===========================================================================*
214 *===========================================================================*/
215 static int map_service(const struct rprocpub
*rpub
)
217 /* Map a new service by registering its label. */
218 struct data_store
*dsp
;
220 /* Allocate a new data slot. */
221 if((dsp
= alloc_data_slot()) == NULL
) {
225 /* Set attributes. */
226 strcpy(dsp
->key
, rpub
->label
);
227 dsp
->u
.u32
= (u32_t
) rpub
->endpoint
;
228 strcpy(dsp
->owner
, "rs");
229 dsp
->flags
= DSF_IN_USE
| DSF_TYPE_LABEL
;
231 /* Update subscribers having a matching subscription. */
232 update_subscribers(dsp
, 1);
237 /*===========================================================================*
238 * sef_cb_init_fresh *
239 *===========================================================================*/
240 int sef_cb_init_fresh(int UNUSED(type
), sef_init_info_t
*info
)
242 /* Initialize the data store server. */
244 struct rprocpub rprocpub
[NR_BOOT_PROCS
];
246 /* Reset data store: data and subscriptions. */
247 for(i
= 0; i
< NR_DS_KEYS
; i
++) {
248 ds_store
[i
].flags
= 0;
250 for(i
= 0; i
< NR_DS_SUBS
; i
++) {
251 ds_subs
[i
].flags
= 0;
254 /* Map all the services in the boot image. */
255 if((r
= sys_safecopyfrom(RS_PROC_NR
, info
->rproctab_gid
, 0,
256 (vir_bytes
) rprocpub
, sizeof(rprocpub
))) != OK
) {
257 panic("sys_safecopyfrom failed: %d", r
);
259 for(i
=0;i
< NR_BOOT_PROCS
;i
++) {
260 if(rprocpub
[i
].in_use
) {
261 if((r
= map_service(&rprocpub
[i
])) != OK
) {
262 panic("unable to map service: %d", r
);
270 /*===========================================================================*
272 *===========================================================================*/
273 int do_publish(message
*m_ptr
)
275 struct data_store
*dsp
;
276 char key_name
[DS_MAX_KEYLEN
];
278 int flags
= m_ptr
->DS_FLAGS
;
282 /* Lookup the source. */
283 source
= ds_getprocname(m_ptr
->m_source
);
287 /* Only RS can publish labels. */
288 if((flags
& DSF_TYPE_LABEL
) && m_ptr
->m_source
!= RS_PROC_NR
)
292 if((r
= get_key_name(m_ptr
, key_name
)) != OK
)
295 /* Lookup the entry. */
296 dsp
= lookup_entry(key_name
, flags
& DSF_MASK_TYPE
);
297 /* If type is LABEL, also try to lookup the entry by num. */
298 if((flags
& DSF_TYPE_LABEL
) && (dsp
== NULL
))
299 dsp
= lookup_label_entry(m_ptr
->DS_VAL
);
302 /* The entry doesn't exist, allocate a new data slot. */
303 if((dsp
= alloc_data_slot()) == NULL
)
305 } else if (flags
& DSF_OVERWRITE
) {
307 if(!check_auth(dsp
, m_ptr
->m_source
, DSF_PRIV_OVERWRITE
))
310 /* Don't overwrite and return error. */
315 switch(flags
& DSF_MASK_TYPE
) {
318 dsp
->u
.u32
= m_ptr
->DS_VAL
;
322 length
= m_ptr
->DS_VAL_LEN
;
323 /* Allocate a new data buffer if necessary. */
324 if(!(dsp
->flags
& DSF_IN_USE
)) {
325 if((dsp
->u
.mem
.data
= malloc(length
)) == NULL
)
327 dsp
->u
.mem
.reallen
= length
;
328 } else if(length
> dsp
->u
.mem
.reallen
) {
329 free(dsp
->u
.mem
.data
);
330 if((dsp
->u
.mem
.data
= malloc(length
)) == NULL
)
332 dsp
->u
.mem
.reallen
= length
;
335 /* Copy the memory range. */
336 r
= sys_safecopyfrom(m_ptr
->m_source
, (cp_grant_id_t
) m_ptr
->DS_VAL
,
337 0, (vir_bytes
) dsp
->u
.mem
.data
, length
);
339 printf("DS: publish: memory map/copy failed from %d: %d\n",
341 free(dsp
->u
.mem
.data
);
344 dsp
->u
.mem
.length
= length
;
345 if(flags
& DSF_TYPE_STR
) {
346 ((char*)dsp
->u
.mem
.data
)[length
-1] = '\0';
353 /* Set attributes. */
354 strcpy(dsp
->key
, key_name
);
355 strcpy(dsp
->owner
, source
);
356 dsp
->flags
= DSF_IN_USE
| (flags
& DSF_MASK_INTERNAL
);
358 /* Update subscribers having a matching subscription. */
359 update_subscribers(dsp
, 1);
364 /*===========================================================================*
366 *===========================================================================*/
367 int do_retrieve(message
*m_ptr
)
369 struct data_store
*dsp
;
370 char key_name
[DS_MAX_KEYLEN
];
371 int flags
= m_ptr
->DS_FLAGS
;
372 int type
= flags
& DSF_MASK_TYPE
;
377 if((r
= get_key_name(m_ptr
, key_name
)) != OK
)
380 /* Lookup the entry. */
381 if((dsp
= lookup_entry(key_name
, type
)) == NULL
)
383 if(!check_auth(dsp
, m_ptr
->m_source
, DSF_PRIV_RETRIEVE
))
386 /* Copy the requested data. */
390 m_ptr
->DS_VAL
= dsp
->u
.u32
;
394 length
= MIN(m_ptr
->DS_VAL_LEN
, dsp
->u
.mem
.length
);
395 r
= sys_safecopyto(m_ptr
->m_source
, (cp_grant_id_t
) m_ptr
->DS_VAL
, 0,
396 (vir_bytes
) dsp
->u
.mem
.data
, length
);
398 printf("DS: retrieve: copy failed to %d: %d\n",
402 m_ptr
->DS_VAL_LEN
= length
;
411 /*===========================================================================*
412 * do_retrieve_label *
413 *===========================================================================*/
414 int do_retrieve_label(const message
*m_ptr
)
416 struct data_store
*dsp
;
419 /* Lookup the label entry. */
420 if((dsp
= lookup_label_entry(m_ptr
->DS_VAL
)) == NULL
)
423 /* Copy the key name. */
424 r
= sys_safecopyto(m_ptr
->m_source
,
425 (cp_grant_id_t
) m_ptr
->DS_KEY_GRANT
, (vir_bytes
) 0,
426 (vir_bytes
) dsp
->key
, strlen(dsp
->key
) + 1);
428 printf("DS: copy failed from %d: %d\n", m_ptr
->m_source
, r
);
435 /*===========================================================================*
437 *===========================================================================*/
438 int do_subscribe(message
*m_ptr
)
440 char regex
[DS_MAX_KEYLEN
+2];
441 struct subscription
*subp
;
447 /* Find the owner. */
448 owner
= ds_getprocname(m_ptr
->m_source
);
452 /* See if the owner already has an existing subscription. */
453 if((subp
= lookup_sub(owner
)) == NULL
) {
454 /* The subscription doesn't exist, allocate a new one. */
455 if((subp
= alloc_sub_slot()) == NULL
)
457 } else if(!(m_ptr
->DS_FLAGS
& DSF_OVERWRITE
)) {
458 /* The subscription exists but we can't overwrite, return error. */
462 /* Copy key name from the caller. Anchor the subscription with "^regexp$" so
463 * substrings don't match. The caller will probably not expect this,
464 * and the usual case is for a complete match.
467 if((r
= get_key_name(m_ptr
, regex
+1)) != OK
)
471 /* Compile regular expression. */
472 if((e
=regcomp(&subp
->regex
, regex
, REG_EXTENDED
)) != 0) {
473 regerror(e
, &subp
->regex
, errbuf
, sizeof(errbuf
));
474 printf("DS: subscribe: regerror: %s\n", errbuf
);
478 /* If type_set = 0, then subscribe all types. */
479 type_set
= m_ptr
->DS_FLAGS
& DSF_MASK_TYPE
;
481 type_set
= DSF_MASK_TYPE
;
483 subp
->flags
= DSF_IN_USE
| type_set
;
484 strcpy(subp
->owner
, owner
);
485 for(b
= 0; b
< BITMAP_CHUNKS(NR_DS_KEYS
); b
++)
486 subp
->old_subs
[b
] = 0;
488 /* See if caller requested an instant initial list. */
489 if(m_ptr
->DS_FLAGS
& DSF_INITIAL
) {
490 int i
, match_found
= FALSE
;
491 for(i
= 0; i
< NR_DS_KEYS
; i
++) {
492 if(!(ds_store
[i
].flags
& DSF_IN_USE
))
494 if(!(ds_store
[i
].flags
& type_set
))
496 if(!check_sub_match(subp
, &ds_store
[i
], m_ptr
->m_source
))
499 SET_BIT(subp
->old_subs
, i
);
503 /* Notify in case of match. */
505 notify(m_ptr
->m_source
);
511 /*===========================================================================*
513 *===========================================================================*/
514 int do_check(message
*m_ptr
)
516 struct subscription
*subp
;
518 endpoint_t entry_owner_e
;
521 /* Find the subscription owner. */
522 owner
= ds_getprocname(m_ptr
->m_source
);
526 /* Lookup the owner's subscription. */
527 if((subp
= lookup_sub(owner
)) == NULL
)
530 /* Look for an updated entry the subscriber is interested in. */
531 for(i
= 0; i
< NR_DS_KEYS
; i
++) {
532 if(GET_BIT(subp
->old_subs
, i
))
538 /* Copy the key name. */
539 r
= sys_safecopyto(m_ptr
->m_source
,
540 (cp_grant_id_t
) m_ptr
->DS_KEY_GRANT
, (vir_bytes
) 0,
541 (vir_bytes
) ds_store
[i
].key
, strlen(ds_store
[i
].key
) + 1);
543 printf("DS: check: copy failed from %d: %d\n", m_ptr
->m_source
, r
);
547 /* Copy the type and the owner of the original entry. */
548 entry_owner_e
= ds_getprocep(ds_store
[i
].owner
);
549 m_ptr
->DS_FLAGS
= ds_store
[i
].flags
& DSF_MASK_TYPE
;
550 m_ptr
->DS_OWNER
= entry_owner_e
;
552 /* Mark the entry as no longer updated for the subscriber. */
553 UNSET_BIT(subp
->old_subs
, i
);
558 /*===========================================================================*
560 *===========================================================================*/
561 int do_delete(message
*m_ptr
)
563 struct data_store
*dsp
;
564 char key_name
[DS_MAX_KEYLEN
];
567 int type
= m_ptr
->DS_FLAGS
& DSF_MASK_TYPE
;
570 /* Lookup the source. */
571 source
= ds_getprocname(m_ptr
->m_source
);
576 if((r
= get_key_name(m_ptr
, key_name
)) != OK
)
579 /* Lookup the entry. */
580 if((dsp
= lookup_entry(key_name
, type
)) == NULL
)
583 /* Only the owner can delete. */
584 if(strcmp(dsp
->owner
, source
))
593 /* Clean up subscriptions. */
594 for (i
= 0; i
< NR_DS_SUBS
; i
++) {
595 if ((ds_subs
[i
].flags
& DSF_IN_USE
)
596 && !strcmp(ds_subs
[i
].owner
, label
)) {
597 ds_subs
[i
].flags
= 0;
601 /* Clean up data entries. */
602 for (i
= 0; i
< NR_DS_KEYS
; i
++) {
603 if ((ds_store
[i
].flags
& DSF_IN_USE
)
604 && !strcmp(ds_store
[i
].owner
, label
)) {
605 update_subscribers(&ds_store
[i
], 0);
607 ds_store
[i
].flags
= 0;
613 free(dsp
->u
.mem
.data
);
619 /* Update subscribers having a matching subscription. */
620 update_subscribers(dsp
, 0);
622 /* Clear the entry. */
628 /*===========================================================================*
630 *===========================================================================*/
631 int do_getsysinfo(const message
*m_ptr
)
637 switch(m_ptr
->SI_WHAT
) {
639 src_addr
= (vir_bytes
)ds_store
;
640 length
= sizeof(struct data_store
) * NR_DS_KEYS
;
646 if (length
!= m_ptr
->SI_SIZE
)
649 if (OK
!= (s
=sys_datacopy(SELF
, src_addr
,
650 m_ptr
->m_source
, (vir_bytes
)m_ptr
->SI_WHERE
, length
))) {
651 printf("DS: copy failed: %d\n", s
);