2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: lookup.c /main/4 1995/11/09 12:46:28 rswiston $ */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company
26 * (c) Copyright 1993, 1994 International Business Machines Corp.
27 * (c) Copyright 1993, 1994 Novell, Inc.
28 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
31 #include <EUSCompat.h>
41 #if !defined(CSRG_BASED)
45 #include <sys/systeminfo.h>
48 #include "cmscalendar.h"
64 #define TIME_BUF_LEN 20
66 /******************************************************************************
67 * forward declaration of static functions used within the file
68 ******************************************************************************/
69 static CSA_return_code _AddToLinkedEntries(cms_entry *eptr, cms_entry **head,
70 cms_entry **tail, boolean_t sort, boolean_t time_only);
71 static CSA_return_code _EnumerateSequence(char *sender, uint access,
72 List_node *lnode, time_t start1,
74 boolean_t no_end_time_range, time_t end1,
75 time_t end2, CSA_uint32 num_attrs,
76 cms_attribute *attrs, CSA_enum *ops,
77 cms_entry **head, cms_entry **tail);
78 static CSA_return_code _GetEntryAttrsByName(_DtCmsCalendar *cal,
79 cms_entry *entry, uint num_names,
80 cms_attr_name *names, uint *num_attrs_r,
81 cms_attribute **attrs_r);
82 static CSA_return_code _GetAllEntryAttrs(cms_entry *entry, uint *num_attrs_r,
83 cms_attribute **attrs_r);
85 /*****************************************************************************
86 * extern functions used in the library
87 *****************************************************************************/
89 extern CSA_return_code
90 _DtCmsLookupEntriesById(
94 boolean_t no_start_time_range,
95 boolean_t no_end_time_range,
101 CSA_uint32 num_attrs,
102 cms_attribute *attrs,
106 CSA_return_code stat = CSA_SUCCESS;
107 CSA_return_code stat2 = CSA_SUCCESS;
108 cms_entry *eptr, *head = NULL, *tail = NULL;
113 if (no_start_time_range) {
118 /* do lookup on repeating entries first */
119 stat = _DtCmsEnumerateSequenceById(cal, sender, access,
120 no_start_time_range, no_end_time_range, start1, start2,
121 end1, end2, id, num_attrs, attrs, ops, &head);
123 if (stat != CSA_X_DT_E_ENTRY_NOT_FOUND) {
124 if (stat == CSA_SUCCESS)
132 while ((eptr = (cms_entry *)rb_lookup_next_larger(cal->tree,
133 (caddr_t)&key)) && eptr->key.time < start2) {
134 if (eptr->key.id != id) {
135 key.time = eptr->key.time;
136 key.id = eptr->key.id;
138 aptr = &eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I];
139 if (!no_end_time_range) {
140 if (aptr->value == NULL)
141 return (CSA_SUCCESS);
143 _csa_iso8601_to_tick(
144 aptr->value->item.date_time_value,
147 if (endtick <= end1 || endtick >= end2)
148 return (CSA_SUCCESS);
151 if (_DtCmsMatchAttributes(eptr, num_attrs, attrs, ops)
152 && ( ((stat2 = _DtCmsCheckViewAccess(sender, access, eptr)) == CSA_SUCCESS) || (stat2 == CSA_E_TIME_ONLY) ) ) {
153 stat = _AddToLinkedEntries(eptr, &head, &tail,
161 return (CSA_SUCCESS);
164 extern CSA_return_code
171 boolean_t no_end_time_range,
174 CSA_uint32 num_attrs,
175 cms_attribute *attrs,
179 CSA_return_code stat = CSA_SUCCESS;
180 CSA_return_code stat2 = CSA_SUCCESS;
181 cms_entry *eptr, *head = NULL, *tail = NULL;
187 /* do lookup on one-time entries first */
190 while ((eptr = (cms_entry *)rb_lookup_next_larger(cal->tree,
191 (caddr_t)&key)) && eptr->key.time < start2) {
193 aptr = &eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I];
195 if (!no_end_time_range) {
196 if (aptr->value == NULL)
199 _csa_iso8601_to_tick(aptr->value->item.date_time_value,
202 if (endtick <= end1 || endtick >= end2)
206 if (_DtCmsMatchAttributes(eptr, num_attrs, attrs, ops) &&
207 _DtCmsCheckViewAccess(sender, access, eptr) == CSA_SUCCESS)
209 /* the last argument "sort" is set to B_FALSE,
210 * because the entries are in order already
211 * as we get them out from the tree;
212 * we don't want to sort it again
214 if ((stat = _AddToLinkedEntries(eptr, &head, &tail,
215 B_FALSE, B_FALSE)) != CSA_SUCCESS)
220 key.time = eptr->key.time;
221 key.id = eptr->key.id;
224 /* do lookup on repeating entries */
225 lnode = cal->list->root;
226 while (lnode != NULL && stat == CSA_SUCCESS) {
228 stat = _EnumerateSequence(sender, access, lnode, start1, start2,
229 no_end_time_range, end1, end2, num_attrs, attrs,
232 lnode = hc_lookup_next(lnode);
235 if (stat == CSA_SUCCESS)
238 _DtCm_free_cms_entries(head);
243 extern CSA_return_code
244 _DtCmsEnumerateSequenceById(
248 boolean_t no_start_time_range,
249 boolean_t no_end_time_range,
255 CSA_uint32 num_attrs,
256 cms_attribute *attrs,
260 CSA_return_code stat;
261 cms_entry *head = NULL, *tail = NULL;
266 lnode = hc_lookup_node(cal->list, (caddr_t)&key);
268 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
270 if ( ((stat = _DtCmsCheckViewAccess(sender, access,
271 (cms_entry *)lnode->data)) != CSA_SUCCESS) && (stat != CSA_E_TIME_ONLY) )
275 if (no_start_time_range && no_end_time_range) {
276 if (_DtCmsMatchAttributes((cms_entry *)lnode->data, num_attrs,
278 stat = _DtCmsGetCmsEntryForClient(
279 (cms_entry *)lnode->data, entries,B_FALSE);
282 stat = _EnumerateSequence(sender, access, lnode, start1, start2,
283 no_end_time_range, end1, end2, num_attrs, attrs, ops,
286 if (stat == CSA_SUCCESS)
289 _DtCm_free_cms_entries(head);
295 extern CSA_return_code
296 _DtCmsLookupEntriesByKey(
303 cms_attr_name *names,
304 cms_get_entry_attr_res_item **res)
306 CSA_return_code stat = CSA_SUCCESS;
307 cms_get_entry_attr_res_item *eptr, *head;
310 for (i = 0, head = NULL; i < num_keys; i++) {
311 if ((stat = _DtCmsGetEntryAttrByKey(cal, user, access, keys[i],
312 num_names, names, NULL, &eptr)) == CSA_SUCCESS) {
316 if (head) _DtCmsFreeEntryAttrResItem(head);
322 return (CSA_SUCCESS);
326 * this routine returns either a cms_entry or
327 * an cms_get_entry_attr_res_item structure
328 * depending which output argument is not null
330 extern CSA_return_code
331 _DtCmsGetEntryAttrByKey(
337 cms_attr_name *names,
339 cms_get_entry_attr_res_item **res_r)
341 CSA_return_code stat;
342 CSA_return_code stat2;
343 cms_entry *entry = NULL;
345 char sbuf[TIME_BUF_LEN], ebuf[TIME_BUF_LEN];
346 time_t firsttick = 0;
348 cms_get_entry_attr_res_item *res = NULL;
350 if (entry_r == NULL && res_r == NULL)
351 return (CSA_E_INVALID_PARAMETER);
353 if (res_r && (res = (cms_get_entry_attr_res_item *)calloc(1,
354 sizeof(cms_get_entry_attr_res_item))) == NULL)
355 return (CSA_E_INSUFFICIENT_MEMORY);
357 /* do lookup on one-time entries first */
358 if ((entry = (cms_entry *)rb_lookup(cal->tree, (caddr_t)&key)) == NULL)
360 if ((lnode = (List_node *)hc_lookup_node(cal->list,
361 (caddr_t)&key)) != NULL)
363 entry = (cms_entry *)lnode->data;
364 if (_DtCmsInExceptionList(entry, key.time))
369 if ( (entry == NULL) || ( ((stat2 = _DtCmsCheckViewAccess(user, access, entry)) != CSA_SUCCESS) && (stat2 != CSA_E_TIME_ONLY)) ) {
371 stat = CSA_X_DT_E_ENTRY_NOT_FOUND;
373 stat = CSA_E_NO_AUTHORITY;
381 return (CSA_SUCCESS);
385 if (entry->key.time != key.time) {
386 /* set start and end time of the instance */
387 firsttick = entry->key.time;
388 entry->key.time = key.time;
390 stime = entry->attrs[CSA_ENTRY_ATTR_START_DATE_I].value->\
391 item.date_time_value;
392 _csa_tick_to_iso8601(key.time, sbuf);
393 entry->attrs[CSA_ENTRY_ATTR_START_DATE_I].value->\
394 item.date_time_value = sbuf;
396 if (entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].value) {
397 etime = entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].\
398 value->item.date_time_value;
399 _csa_tick_to_iso8601(key.time + lnode->duration, ebuf);
400 entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].value->\
401 item.date_time_value = ebuf;
407 stat = _DtCmsGetCmsEntryForClient(entry, entry_r,B_FALSE);
410 stat = _GetAllEntryAttrs(entry, &res->num_attrs,
413 stat = _GetEntryAttrsByName(cal, entry, num_names,
414 names, &res->num_attrs, &res->attrs);
416 if (stat == CSA_SUCCESS) {
424 entry->key.time = firsttick;
425 entry->attrs[CSA_ENTRY_ATTR_START_DATE_I].value->\
426 item.date_time_value = stime;
427 if (entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].value)
428 entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].value->\
429 item.date_time_value = etime;
435 /*****************************************************************************
436 * static functions used within the file
437 *****************************************************************************/
439 static CSA_return_code
447 CSA_return_code stat;
448 cms_entry *newptr, *prev, *ptr;
450 if ((stat = _DtCmsGetCmsEntryForClient(eptr, &newptr,time_only)) != CSA_SUCCESS)
453 if (sort == B_FALSE) {
454 /* just add to the end of the list */
459 (*tail)->next = newptr;
463 /* add item in ascending order */
464 for (prev = NULL, ptr = *head; ptr != NULL;
465 prev = ptr, ptr = ptr->next) {
466 if (eptr->key.time <= ptr->key.time)
480 return (CSA_SUCCESS);
483 static CSA_return_code
490 boolean_t no_end_time_range,
493 CSA_uint32 num_attrs,
494 cms_attribute *attrs,
499 CSA_return_code stat = CSA_SUCCESS;
500 CSA_return_code stat2 = CSA_SUCCESS;
502 time_t fsttick, tick;
503 RepeatEventState *restate = NULL;
505 eptr = (cms_entry *)lnode->data;
506 fsttick = eptr->key.time;
508 if (lnode->lasttick == 0) {
509 lnode->lasttick = LastTick(fsttick, lnode->re);
510 lnode->duration = _DtCmsGetDuration(eptr);
513 if (lnode->lasttick <= start1 || fsttick >= start2 ||
514 (!no_end_time_range &&
515 eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].value == NULL) ||
516 (!no_end_time_range && (lnode->lasttick+lnode->duration) <= end1) ||
517 (!no_end_time_range && (fsttick + lnode->duration) >= end2) ||
518 _DtCmsCheckViewAccess(sender, access, eptr) ||
519 !_DtCmsMatchAttributes(eptr, num_attrs, attrs, ops))
520 return (CSA_SUCCESS);
522 if (!no_end_time_range && start1 < (end1 - lnode->duration))
523 start1 = end1 - lnode->duration;
525 if (!no_end_time_range && ((end2 - lnode->duration) < start2))
526 start2 = end2 - lnode->duration;
528 for (tick = ClosestTick(start1, fsttick, lnode->re, &restate);
529 stat == CSA_SUCCESS && tick < start2;
530 tick = NextTick(tick, fsttick, lnode->re, restate))
533 char sbuf[TIME_BUF_LEN], ebuf[TIME_BUF_LEN];
535 if (tick <= 0 || tick > lnode->lasttick)
538 if (tick <= start1 || _DtCmsInExceptionList(eptr, tick))
541 /* set start and end time of the instance */
542 eptr->key.time = tick;
544 stime = eptr->attrs[CSA_ENTRY_ATTR_START_DATE_I].value->\
545 item.date_time_value;
546 _csa_tick_to_iso8601(tick, sbuf);
547 eptr->attrs[CSA_ENTRY_ATTR_START_DATE_I].value->\
548 item.date_time_value = sbuf;
550 if (eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].value) {
551 etime = eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].\
552 value->item.date_time_value;
553 _csa_tick_to_iso8601(tick + lnode->duration, ebuf);
554 eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].value->\
555 item.date_time_value = ebuf;
558 stat = _AddToLinkedEntries(eptr, head, tail, B_TRUE,B_FALSE);
560 eptr->key.time = fsttick;
561 eptr->attrs[CSA_ENTRY_ATTR_START_DATE_I].value->\
562 item.date_time_value = stime;
563 if (eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].value)
564 eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].value->\
565 item.date_time_value = etime;
572 static CSA_return_code
573 _GetEntryAttrsByName(
577 cms_attr_name *names,
579 cms_attribute **attrs_r)
581 CSA_return_code stat = CSA_SUCCESS;
582 cms_attribute *attrs;
585 if ((attrs = calloc(1, sizeof(cms_attribute)*num_names)) == NULL)
586 return (CSA_E_INSUFFICIENT_MEMORY);
588 /* return all attrs names with hash number
589 * so that caller knows which one does not
590 * have value and which one does not even exist
592 for (i = 0; i < num_names && stat == CSA_SUCCESS; i++) {
593 if (names[i].name == NULL)
596 if (names[i].num <= 0)
597 names[i].num = _DtCm_get_index_from_table(
598 cal->entry_tbl, names[i].name);
600 if (names[i].num > 0) {
601 stat = _DtCm_copy_cms_attribute(&attrs[i],
602 &entry->attrs[names[i].num], B_TRUE);
604 attrs[i].name.num = -1;
605 if ((attrs[i].name.name = strdup(names[i].name))==NULL)
606 stat = CSA_E_INSUFFICIENT_MEMORY;
610 if (stat == CSA_SUCCESS) {
611 *num_attrs_r = num_names;
614 _DtCm_free_cms_attributes(i, attrs);
621 static CSA_return_code
625 cms_attribute **attrs_r)
627 CSA_return_code stat = CSA_SUCCESS;
628 cms_attribute *attrs;
631 if ((attrs = calloc(1, sizeof(cms_attribute)*entry->num_attrs)) == NULL)
632 return (CSA_E_INSUFFICIENT_MEMORY);
634 /* first element is not used */
635 for (i = 1, j = 0; i <= entry->num_attrs && stat == CSA_SUCCESS; i++) {
636 if (entry->attrs[i].value) {
637 if ((stat = _DtCm_copy_cms_attribute(&attrs[j],
638 &entry->attrs[i], B_TRUE))
646 if (stat == CSA_SUCCESS) {
656 _DtCm_free_cms_attributes(j, attrs);