1 /* $XConsortium: lookup.c /main/4 1995/11/09 12:46:28 rswiston $ */
3 * (c) Copyright 1993, 1994 Hewlett-Packard Company
4 * (c) Copyright 1993, 1994 International Business Machines Corp.
5 * (c) Copyright 1993, 1994 Novell, Inc.
6 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
21 #include <sys/systeminfo.h>
24 #include "cmscalendar.h"
40 #define TIME_BUF_LEN 20
42 /******************************************************************************
43 * forward declaration of static functions used within the file
44 ******************************************************************************/
45 static CSA_return_code _AddToLinkedEntries(cms_entry *eptr, cms_entry **head,
46 cms_entry **tail, boolean_t sort, boolean_t time_only);
47 static CSA_return_code _EnumerateSequence(char *sender, uint access,
48 List_node *lnode, time_t start1,
50 boolean_t no_end_time_range, time_t end1,
51 time_t end2, CSA_uint32 num_attrs,
52 cms_attribute *attrs, CSA_enum *ops,
53 cms_entry **head, cms_entry **tail);
54 static CSA_return_code _GetEntryAttrsByName(_DtCmsCalendar *cal,
55 cms_entry *entry, uint num_names,
56 cms_attr_name *names, uint *num_attrs_r,
57 cms_attribute **attrs_r);
58 static CSA_return_code _GetAllEntryAttrs(cms_entry *entry, uint *num_attrs_r,
59 cms_attribute **attrs_r);
61 /*****************************************************************************
62 * extern functions used in the library
63 *****************************************************************************/
65 extern CSA_return_code
66 _DtCmsLookupEntriesById(
70 boolean_t no_start_time_range,
71 boolean_t no_end_time_range,
82 CSA_return_code stat = CSA_SUCCESS;
83 CSA_return_code stat2 = CSA_SUCCESS;
84 cms_entry *eptr, *head = NULL, *tail = NULL;
89 if (no_start_time_range) {
94 /* do lookup on repeating entries first */
95 stat = _DtCmsEnumerateSequenceById(cal, sender, access,
96 no_start_time_range, no_end_time_range, start1, start2,
97 end1, end2, id, num_attrs, attrs, ops, &head);
99 if (stat != CSA_X_DT_E_ENTRY_NOT_FOUND) {
100 if (stat == CSA_SUCCESS)
108 while ((eptr = (cms_entry *)rb_lookup_next_larger(cal->tree,
109 (caddr_t)&key)) && eptr->key.time < start2) {
110 if (eptr->key.id != id) {
111 key.time = eptr->key.time;
112 key.id = eptr->key.id;
114 aptr = &eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I];
115 if (!no_end_time_range) {
116 if (aptr->value == NULL)
117 return (CSA_SUCCESS);
119 _csa_iso8601_to_tick(
120 aptr->value->item.date_time_value,
123 if (endtick <= end1 || endtick >= end2)
124 return (CSA_SUCCESS);
127 if (_DtCmsMatchAttributes(eptr, num_attrs, attrs, ops)
128 && ( ((stat2 = _DtCmsCheckViewAccess(sender, access, eptr)) == CSA_SUCCESS) || (stat2 == CSA_E_TIME_ONLY) ) ) {
129 stat = _AddToLinkedEntries(eptr, &head, &tail,
137 return (CSA_SUCCESS);
140 extern CSA_return_code
147 boolean_t no_end_time_range,
150 CSA_uint32 num_attrs,
151 cms_attribute *attrs,
155 CSA_return_code stat = CSA_SUCCESS;
156 CSA_return_code stat2 = CSA_SUCCESS;
157 cms_entry *eptr, *head = NULL, *tail = NULL;
163 /* do lookup on one-time entries first */
166 while ((eptr = (cms_entry *)rb_lookup_next_larger(cal->tree,
167 (caddr_t)&key)) && eptr->key.time < start2) {
169 aptr = &eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I];
171 if (!no_end_time_range) {
172 if (aptr->value == NULL)
175 _csa_iso8601_to_tick(aptr->value->item.date_time_value,
178 if (endtick <= end1 || endtick >= end2)
182 if (_DtCmsMatchAttributes(eptr, num_attrs, attrs, ops) &&
183 _DtCmsCheckViewAccess(sender, access, eptr) == CSA_SUCCESS)
185 /* the last argument "sort" is set to B_FALSE,
186 * because the entries are in order already
187 * as we get them out from the tree;
188 * we don't want to sort it again
190 if ((stat = _AddToLinkedEntries(eptr, &head, &tail,
191 B_FALSE, B_FALSE)) != CSA_SUCCESS)
196 key.time = eptr->key.time;
197 key.id = eptr->key.id;
200 /* do lookup on repeating entries */
201 lnode = cal->list->root;
202 while (lnode != NULL && stat == CSA_SUCCESS) {
204 stat = _EnumerateSequence(sender, access, lnode, start1, start2,
205 no_end_time_range, end1, end2, num_attrs, attrs,
208 lnode = hc_lookup_next(lnode);
211 if (stat == CSA_SUCCESS)
214 _DtCm_free_cms_entries(head);
219 extern CSA_return_code
220 _DtCmsEnumerateSequenceById(
224 boolean_t no_start_time_range,
225 boolean_t no_end_time_range,
231 CSA_uint32 num_attrs,
232 cms_attribute *attrs,
236 CSA_return_code stat;
237 cms_entry *head = NULL, *tail = NULL;
242 lnode = hc_lookup_node(cal->list, (caddr_t)&key);
244 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
246 if ( ((stat = _DtCmsCheckViewAccess(sender, access,
247 (cms_entry *)lnode->data)) != CSA_SUCCESS) && (stat != CSA_E_TIME_ONLY) )
251 if (no_start_time_range && no_end_time_range) {
252 if (_DtCmsMatchAttributes((cms_entry *)lnode->data, num_attrs,
254 stat = _DtCmsGetCmsEntryForClient(
255 (cms_entry *)lnode->data, entries,B_FALSE);
258 stat = _EnumerateSequence(sender, access, lnode, start1, start2,
259 no_end_time_range, end1, end2, num_attrs, attrs, ops,
262 if (stat == CSA_SUCCESS)
265 _DtCm_free_cms_entries(head);
271 extern CSA_return_code
272 _DtCmsLookupEntriesByKey(
279 cms_attr_name *names,
280 cms_get_entry_attr_res_item **res)
282 CSA_return_code stat = CSA_SUCCESS;
283 cms_get_entry_attr_res_item *eptr, *head;
286 for (i = 0, head = NULL; i < num_keys; i++) {
287 if ((stat = _DtCmsGetEntryAttrByKey(cal, user, access, keys[i],
288 num_names, names, NULL, &eptr)) == CSA_SUCCESS) {
292 if (head) _DtCmsFreeEntryAttrResItem(head);
298 return (CSA_SUCCESS);
302 * this routine returns either a cms_entry or
303 * an cms_get_entry_attr_res_item structure
304 * depending which output argument is not null
306 extern CSA_return_code
307 _DtCmsGetEntryAttrByKey(
313 cms_attr_name *names,
315 cms_get_entry_attr_res_item **res_r)
317 CSA_return_code stat;
318 CSA_return_code stat2;
319 cms_entry *entry = NULL;
321 char sbuf[TIME_BUF_LEN], ebuf[TIME_BUF_LEN];
322 time_t firsttick = 0;
324 cms_get_entry_attr_res_item *res;
326 if (entry_r == NULL && res_r == NULL)
327 return (CSA_E_INVALID_PARAMETER);
329 if (res_r && (res = (cms_get_entry_attr_res_item *)calloc(1,
330 sizeof(cms_get_entry_attr_res_item))) == NULL)
331 return (CSA_E_INSUFFICIENT_MEMORY);
333 /* do lookup on one-time entries first */
334 if ((entry = (cms_entry *)rb_lookup(cal->tree, (caddr_t)&key)) == NULL)
336 if ((lnode = (List_node *)hc_lookup_node(cal->list,
337 (caddr_t)&key)) != NULL)
339 entry = (cms_entry *)lnode->data;
340 if (_DtCmsInExceptionList(entry, key.time))
345 if ( (entry == NULL) || ( ((stat2 = _DtCmsCheckViewAccess(user, access, entry)) != CSA_SUCCESS) && (stat2 != CSA_E_TIME_ONLY)) ) {
347 stat = CSA_X_DT_E_ENTRY_NOT_FOUND;
349 stat = CSA_E_NO_AUTHORITY;
356 return (CSA_SUCCESS);
360 if (entry->key.time != key.time) {
361 /* set start and end time of the instance */
362 firsttick = entry->key.time;
363 entry->key.time = key.time;
365 stime = entry->attrs[CSA_ENTRY_ATTR_START_DATE_I].value->\
366 item.date_time_value;
367 _csa_tick_to_iso8601(key.time, sbuf);
368 entry->attrs[CSA_ENTRY_ATTR_START_DATE_I].value->\
369 item.date_time_value = sbuf;
371 if (entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].value) {
372 etime = entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].\
373 value->item.date_time_value;
374 _csa_tick_to_iso8601(key.time + lnode->duration, ebuf);
375 entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].value->\
376 item.date_time_value = ebuf;
381 stat = _DtCmsGetCmsEntryForClient(entry, entry_r,B_FALSE);
384 stat = _GetAllEntryAttrs(entry, &res->num_attrs,
387 stat = _GetEntryAttrsByName(cal, entry, num_names,
388 names, &res->num_attrs, &res->attrs);
390 if (stat == CSA_SUCCESS) {
398 entry->key.time = firsttick;
399 entry->attrs[CSA_ENTRY_ATTR_START_DATE_I].value->\
400 item.date_time_value = stime;
401 if (entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].value)
402 entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].value->\
403 item.date_time_value = etime;
409 /*****************************************************************************
410 * static functions used within the file
411 *****************************************************************************/
413 static CSA_return_code
421 CSA_return_code stat;
422 cms_entry *newptr, *prev, *ptr;
424 if ((stat = _DtCmsGetCmsEntryForClient(eptr, &newptr,time_only)) != CSA_SUCCESS)
427 if (sort == B_FALSE) {
428 /* just add to the end of the list */
433 (*tail)->next = newptr;
437 /* add item in ascending order */
438 for (prev = NULL, ptr = *head; ptr != NULL;
439 prev = ptr, ptr = ptr->next) {
440 if (eptr->key.time <= ptr->key.time)
454 return (CSA_SUCCESS);
457 static CSA_return_code
464 boolean_t no_end_time_range,
467 CSA_uint32 num_attrs,
468 cms_attribute *attrs,
473 CSA_return_code stat = CSA_SUCCESS;
474 CSA_return_code stat2 = CSA_SUCCESS;
476 time_t fsttick, tick;
477 RepeatEventState *restate;
479 eptr = (cms_entry *)lnode->data;
480 fsttick = eptr->key.time;
482 if (lnode->lasttick == 0) {
483 lnode->lasttick = LastTick(fsttick, lnode->re);
484 lnode->duration = _DtCmsGetDuration(eptr);
487 if (lnode->lasttick <= start1 || fsttick >= start2 ||
488 (!no_end_time_range &&
489 eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].value == NULL) ||
490 (!no_end_time_range && (lnode->lasttick+lnode->duration) <= end1) ||
491 (!no_end_time_range && (fsttick + lnode->duration) >= end2) ||
492 _DtCmsCheckViewAccess(sender, access, eptr) ||
493 !_DtCmsMatchAttributes(eptr, num_attrs, attrs, ops))
494 return (CSA_SUCCESS);
496 if (!no_end_time_range && start1 < (end1 - lnode->duration))
497 start1 = end1 - lnode->duration;
499 if (!no_end_time_range && ((end2 - lnode->duration) < start2))
500 start2 = end2 - lnode->duration;
502 for (tick = ClosestTick(start1, fsttick, lnode->re, &restate);
503 stat == CSA_SUCCESS && tick < start2;
504 tick = NextTick(tick, fsttick, lnode->re, restate))
507 char sbuf[TIME_BUF_LEN], ebuf[TIME_BUF_LEN];
509 if (tick <= 0 || tick > lnode->lasttick)
512 if (tick <= start1 || _DtCmsInExceptionList(eptr, tick))
515 /* set start and end time of the instance */
516 eptr->key.time = tick;
518 stime = eptr->attrs[CSA_ENTRY_ATTR_START_DATE_I].value->\
519 item.date_time_value;
520 _csa_tick_to_iso8601(tick, sbuf);
521 eptr->attrs[CSA_ENTRY_ATTR_START_DATE_I].value->\
522 item.date_time_value = sbuf;
524 if (eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].value) {
525 etime = eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].\
526 value->item.date_time_value;
527 _csa_tick_to_iso8601(tick + lnode->duration, ebuf);
528 eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].value->\
529 item.date_time_value = ebuf;
532 stat = _AddToLinkedEntries(eptr, head, tail, B_TRUE,B_FALSE);
534 eptr->key.time = fsttick;
535 eptr->attrs[CSA_ENTRY_ATTR_START_DATE_I].value->\
536 item.date_time_value = stime;
537 if (eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].value)
538 eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].value->\
539 item.date_time_value = etime;
545 static CSA_return_code
546 _GetEntryAttrsByName(
550 cms_attr_name *names,
552 cms_attribute **attrs_r)
554 CSA_return_code stat = CSA_SUCCESS;
555 cms_attribute *attrs;
558 if ((attrs = calloc(1, sizeof(cms_attribute)*num_names)) == NULL)
559 return (CSA_E_INSUFFICIENT_MEMORY);
561 /* return all attrs names with hash number
562 * so that caller knows which one does not
563 * have value and which one does not even exist
565 for (i = 0; i < num_names && stat == CSA_SUCCESS; i++) {
566 if (names[i].name == NULL)
569 if (names[i].num <= 0)
570 names[i].num = _DtCm_get_index_from_table(
571 cal->entry_tbl, names[i].name);
573 if (names[i].num > 0) {
574 stat = _DtCm_copy_cms_attribute(&attrs[i],
575 &entry->attrs[names[i].num], B_TRUE);
577 attrs[i].name.num = -1;
578 if ((attrs[i].name.name = strdup(names[i].name))==NULL)
579 stat = CSA_E_INSUFFICIENT_MEMORY;
583 if (stat == CSA_SUCCESS) {
584 *num_attrs_r = num_names;
587 _DtCm_free_cms_attributes(i, attrs);
594 static CSA_return_code
598 cms_attribute **attrs_r)
600 CSA_return_code stat = CSA_SUCCESS;
601 cms_attribute *attrs;
604 if ((attrs = calloc(1, sizeof(cms_attribute)*entry->num_attrs)) == NULL)
605 return (CSA_E_INSUFFICIENT_MEMORY);
607 /* first element is not used */
608 for (i = 1, j = 0; i <= entry->num_attrs && stat == CSA_SUCCESS; i++) {
609 if (entry->attrs[i].value) {
610 if ((stat = _DtCm_copy_cms_attribute(&attrs[j],
611 &entry->attrs[i], B_TRUE))
619 if (stat == CSA_SUCCESS) {
629 _DtCm_free_cms_attributes(j, attrs);