1 /* $XConsortium: delete.c /main/4 1995/11/09 12:43:26 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>
23 #include "cmscalendar.h"
39 /******************************************************************************
40 * forward declaration of static functions used within the file
41 ******************************************************************************/
42 static boolean_t _InSequence(List_node *node, time_t time);
43 static CSA_return_code _AddException(cms_attribute *attr, time_t time);
44 static CSA_return_code _AddEndDateToRule(cms_attribute *attr, RepeatEvent *re,
46 static void _TruncateExceptionDates(cms_entry *newe, time_t ltick);
48 /*****************************************************************************
49 * extern functions used in the library
50 *****************************************************************************/
52 extern CSA_return_code
62 List_node *lnode = NULL;
65 if ((entry = (cms_entry *)rb_lookup(cal->tree, (caddr_t)key)) == NULL) {
66 /* find entry in the repeating entry list */
67 if ((lnode = hc_lookup_node(cal->list, (caddr_t)key)) == NULL)
68 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
70 entry = (cms_entry *)lnode->data;
74 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
76 if (sender && (stat = _DtCmsCheckChangeAccess(sender, access, entry))
81 if ((tnode = rb_delete(cal->tree, (caddr_t)key)) != NULL) {
82 _DtCmsObsoleteReminder4Entry(cal->remq, entry, NULL,
86 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
88 _DtCmsObsoleteReminder4Entry(cal->remq, entry, lnode,
90 hc_delete_node(cal->list, lnode);
98 _DtCm_free_cms_entry(entry);
100 return (CSA_SUCCESS);
103 extern CSA_return_code
104 _DtCmsDeleteEntryAndLog(
111 CSA_return_code stat;
114 if ((stat = _DtCmsDeleteEntry(cal, sender, access, key, &entry))
116 if ((stat = _DtCmsV5TransactLog(cal, entry, _DtCmsLogRemove))
118 (void)_DtCmsInsertEntry(cal, entry);
119 _DtCm_free_cms_entry(entry);
123 _DtCm_free_cms_entry(entry);
129 extern CSA_return_code
130 _DtCmsDeleteInstancesAndLog(
139 CSA_return_code stat;
140 cms_entry *entry, *nentry;
144 cms_attribute *tmp_attrs, *aptr;
145 boolean_t delentry = B_FALSE;
147 if ((lnode = hc_lookup_node(cal->list, (caddr_t)key)) == NULL)
148 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
150 entry = (cms_entry *)lnode->data;
152 if ((stat = _DtCmsCheckChangeAccess(sender, access, entry))
156 if (_DtCmsInExceptionList(entry, key->time) ||
157 !_InSequence(lnode, key->time))
158 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
160 if ((stat = _DtCm_copy_cms_entry(entry, &nentry)) != CSA_SUCCESS)
163 if (scope == CSA_SCOPE_ONE)
164 stat = _AddException(
165 &nentry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I],
168 /* check whether we are deleting from fst instance */
169 if (key->time == nentry->key.time)
172 stat = _DtCmsAddEndDateToRule(&nentry->attrs\
173 [CSA_ENTRY_ATTR_RECURRENCE_RULE_I],
174 lnode->re, key->time - 1);
175 lnode->re->re_end_date = key->time - 1;
177 _TruncateExceptionDates(nentry, key->time);
181 if (stat != CSA_SUCCESS) {
182 _DtCm_free_cms_entry(nentry);
187 if ((stat = _DtCmsSetLastUpdate(nentry)) != SUCCESS) {
188 _DtCm_free_cms_entry(nentry);
192 /* remove original entry from log */
193 if ((stat = _DtCmsGetFileSize(cal->calendar, &fsize))
195 _DtCm_free_cms_entry(nentry);
199 if ((stat = _DtCmsV5TransactLog(cal, entry, _DtCmsLogRemove))
201 _DtCm_free_cms_entry(nentry);
205 aptr = &nentry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I];
206 count = CountEvents(nentry->key.time, lnode->re, (aptr->value ?
207 aptr->value->item.date_time_list_value : NULL));
210 if (count == 0 || delentry) {
212 * *** obsolete reminders
214 _DtCmsObsoleteReminder4Entry(cal->remq, entry, lnode,
217 hc_delete_node(cal->list, lnode);
220 _DtCm_free_cms_entry(nentry);
225 _DtCm_free_cms_entry(entry);
231 /* add new entry in memory and log in file */
233 /* update the count */
236 _DtCmsConvertToOnetime(nentry, lnode->re);
237 stat = _DtCmsRbToCsaStat(rb_insert(cal->tree,
238 (caddr_t)nentry, (caddr_t)&(nentry->key)));
240 } else if (count != RE_INFINITY) {
241 nentry->attrs[CSA_ENTRY_ATTR_NUMBER_RECURRENCES_I].\
242 value->item.uint32_value = count;
245 /* the new entry should be copied when it's updated
248 if (stat == CSA_SUCCESS && newe)
249 stat = _DtCm_copy_cms_entry(nentry, newe);
251 if (stat || (stat = _DtCmsV5TransactLog(cal, nentry,
252 _DtCmsLogAdd)) != CSA_SUCCESS) {
253 _DtCmsTruncateFile(cal->calendar, fsize);
254 _DtCm_free_cms_entry(nentry);
255 if (newe) free(*newe);
258 _DtCmsObsoleteReminder4Entry(cal->remq, entry,
260 hc_delete_node(cal->list, lnode);
262 _DtCmsAddReminders4Entry(&cal->remq, nentry, NULL);
264 /* need to do the swap since the original entry
265 * pointer is stored in the reminder info
267 tmp_num = entry->num_attrs;
268 tmp_attrs = entry->attrs;
269 entry->num_attrs = nentry->num_attrs;
270 entry->attrs = nentry->attrs;
271 nentry->num_attrs = tmp_num;
272 nentry->attrs = tmp_attrs;
274 _DtCmsObsoleteReminder4Entry(cal->remq, entry,
276 (scope == CSA_SCOPE_ONE ? B_FALSE :
279 if (scope == CSA_SCOPE_FORWARD ||
280 key->time == lnode->lasttick) {
281 lnode->lasttick = LastTick(
288 *olde = (count == 1) ? entry : nentry;
290 _DtCm_free_cms_entry((count==1)?entry:nentry);
297 /*****************************************************************************
298 * static functions used within the file
299 *****************************************************************************/
302 _InSequence(List_node *node, time_t time)
305 cms_entry *entry = (cms_entry *)node->data;
306 RepeatEventState *restate;
308 for (tick = ClosestTick(time, entry->key.time, node->re, &restate);
309 tick <= node->lasttick;
310 tick = NextTick(tick, entry->key.time, node->re, restate))
312 if (tick <= 0 || tick > node->lasttick)
322 static CSA_return_code
323 _AddException(cms_attribute *attr, time_t time)
325 CSA_date_time_entry *dt, *dlist, *prev;
326 cms_attribute_value *val;
330 if ((dt = (CSA_date_time_entry *)calloc(1, sizeof(CSA_date_time_entry)))
332 return (CSA_E_INSUFFICIENT_MEMORY);
334 if (_csa_tick_to_iso8601(time, buf)) {
336 return (CSA_E_INVALID_DATE_TIME);
337 } else if ((dt->date_time = strdup(buf)) == NULL) {
339 return (CSA_E_INSUFFICIENT_MEMORY);
342 if (attr->value == NULL) {
343 if ((val = (cms_attribute_value *)calloc(1,
344 sizeof(cms_attribute_value))) == NULL) {
347 return (CSA_E_INSUFFICIENT_MEMORY);
350 val->type = CSA_VALUE_DATE_TIME_LIST;
353 if (attr->value->item.date_time_list_value == NULL) {
354 val->item.date_time_list_value = dt;
356 for (dlist = attr->value->item.date_time_list_value, prev=NULL;
358 prev = dlist, dlist = dlist->next) {
359 _csa_iso8601_to_tick(dlist->date_time, &tick);
366 attr->value->item.date_time_list_value = dt;
371 return (CSA_SUCCESS);
375 _TruncateExceptionDates(cms_entry *newe, time_t ltick)
378 CSA_date_time_list dt, prev, head;
380 if (newe->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value == NULL ||
381 newe->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value->item.\
382 date_time_list_value == NULL)
385 head = newe->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value->item.\
386 date_time_list_value;
388 for (dt = head, prev = NULL; dt != NULL; prev = dt, dt = dt->next) {
389 _csa_iso8601_to_tick(dt->date_time, &tick);
393 _DtCm_free_date_time_list(dt);
396 [CSA_ENTRY_ATTR_EXCEPTION_DATES_I].\
398 newe->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].\