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 librararies 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: delete.c /main/4 1995/11/09 12:43:26 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>
43 #include <sys/systeminfo.h>
45 #include "cmscalendar.h"
61 /******************************************************************************
62 * forward declaration of static functions used within the file
63 ******************************************************************************/
64 static boolean_t _InSequence(List_node *node, time_t time);
65 static CSA_return_code _AddException(cms_attribute *attr, time_t time);
66 static CSA_return_code _AddEndDateToRule(cms_attribute *attr, RepeatEvent *re,
68 static void _TruncateExceptionDates(cms_entry *newe, time_t ltick);
70 /*****************************************************************************
71 * extern functions used in the library
72 *****************************************************************************/
74 extern CSA_return_code
84 List_node *lnode = NULL;
87 if ((entry = (cms_entry *)rb_lookup(cal->tree, (caddr_t)key)) == NULL) {
88 /* find entry in the repeating entry list */
89 if ((lnode = hc_lookup_node(cal->list, (caddr_t)key)) == NULL)
90 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
92 entry = (cms_entry *)lnode->data;
96 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
98 if (sender && (stat = _DtCmsCheckChangeAccess(sender, access, entry))
103 if ((tnode = rb_delete(cal->tree, (caddr_t)key)) != NULL) {
104 _DtCmsObsoleteReminder4Entry(cal->remq, entry, NULL,
108 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
110 _DtCmsObsoleteReminder4Entry(cal->remq, entry, lnode,
112 hc_delete_node(cal->list, lnode);
120 _DtCm_free_cms_entry(entry);
122 return (CSA_SUCCESS);
125 extern CSA_return_code
126 _DtCmsDeleteEntryAndLog(
133 CSA_return_code stat;
136 if ((stat = _DtCmsDeleteEntry(cal, sender, access, key, &entry))
138 if ((stat = _DtCmsV5TransactLog(cal, entry, _DtCmsLogRemove))
140 (void)_DtCmsInsertEntry(cal, entry);
141 _DtCm_free_cms_entry(entry);
145 _DtCm_free_cms_entry(entry);
151 extern CSA_return_code
152 _DtCmsDeleteInstancesAndLog(
161 CSA_return_code stat;
162 cms_entry *entry, *nentry;
166 cms_attribute *tmp_attrs, *aptr;
167 boolean_t delentry = B_FALSE;
169 if ((lnode = hc_lookup_node(cal->list, (caddr_t)key)) == NULL)
170 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
172 entry = (cms_entry *)lnode->data;
174 if ((stat = _DtCmsCheckChangeAccess(sender, access, entry))
178 if (_DtCmsInExceptionList(entry, key->time) ||
179 !_InSequence(lnode, key->time))
180 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
182 if ((stat = _DtCm_copy_cms_entry(entry, &nentry)) != CSA_SUCCESS)
185 if (scope == CSA_SCOPE_ONE)
186 stat = _AddException(
187 &nentry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I],
190 /* check whether we are deleting from fst instance */
191 if (key->time == nentry->key.time)
194 stat = _DtCmsAddEndDateToRule(&nentry->attrs\
195 [CSA_ENTRY_ATTR_RECURRENCE_RULE_I],
196 lnode->re, key->time - 1);
197 lnode->re->re_end_date = key->time - 1;
199 _TruncateExceptionDates(nentry, key->time);
203 if (stat != CSA_SUCCESS) {
204 _DtCm_free_cms_entry(nentry);
209 if ((stat = _DtCmsSetLastUpdate(nentry)) != SUCCESS) {
210 _DtCm_free_cms_entry(nentry);
214 /* remove original entry from log */
215 if ((stat = _DtCmsGetFileSize(cal->calendar, &fsize))
217 _DtCm_free_cms_entry(nentry);
221 if ((stat = _DtCmsV5TransactLog(cal, entry, _DtCmsLogRemove))
223 _DtCm_free_cms_entry(nentry);
227 aptr = &nentry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I];
228 count = CountEvents(nentry->key.time, lnode->re, (aptr->value ?
229 aptr->value->item.date_time_list_value : NULL));
232 if (count == 0 || delentry) {
234 * *** obsolete reminders
236 _DtCmsObsoleteReminder4Entry(cal->remq, entry, lnode,
239 hc_delete_node(cal->list, lnode);
242 _DtCm_free_cms_entry(nentry);
247 _DtCm_free_cms_entry(entry);
253 /* add new entry in memory and log in file */
255 /* update the count */
258 _DtCmsConvertToOnetime(nentry, lnode->re);
259 stat = _DtCmsRbToCsaStat(rb_insert(cal->tree,
260 (caddr_t)nentry, (caddr_t)&(nentry->key)));
262 } else if (count != RE_INFINITY) {
263 nentry->attrs[CSA_ENTRY_ATTR_NUMBER_RECURRENCES_I].\
264 value->item.uint32_value = count;
267 /* the new entry should be copied when it's updated
270 if (stat == CSA_SUCCESS && newe)
271 stat = _DtCm_copy_cms_entry(nentry, newe);
273 if (stat || (stat = _DtCmsV5TransactLog(cal, nentry,
274 _DtCmsLogAdd)) != CSA_SUCCESS) {
275 _DtCmsTruncateFile(cal->calendar, fsize);
276 _DtCm_free_cms_entry(nentry);
277 if (newe) free(*newe);
280 _DtCmsObsoleteReminder4Entry(cal->remq, entry,
282 hc_delete_node(cal->list, lnode);
284 _DtCmsAddReminders4Entry(&cal->remq, nentry, NULL);
286 /* need to do the swap since the original entry
287 * pointer is stored in the reminder info
289 tmp_num = entry->num_attrs;
290 tmp_attrs = entry->attrs;
291 entry->num_attrs = nentry->num_attrs;
292 entry->attrs = nentry->attrs;
293 nentry->num_attrs = tmp_num;
294 nentry->attrs = tmp_attrs;
296 _DtCmsObsoleteReminder4Entry(cal->remq, entry,
298 (scope == CSA_SCOPE_ONE ? B_FALSE :
301 if (scope == CSA_SCOPE_FORWARD ||
302 key->time == lnode->lasttick) {
303 lnode->lasttick = LastTick(
310 *olde = (count == 1) ? entry : nentry;
312 _DtCm_free_cms_entry((count==1)?entry:nentry);
319 /*****************************************************************************
320 * static functions used within the file
321 *****************************************************************************/
324 _InSequence(List_node *node, time_t time)
327 cms_entry *entry = (cms_entry *)node->data;
328 RepeatEventState *restate;
330 for (tick = ClosestTick(time, entry->key.time, node->re, &restate);
331 tick <= node->lasttick;
332 tick = NextTick(tick, entry->key.time, node->re, restate))
334 if (tick <= 0 || tick > node->lasttick)
344 static CSA_return_code
345 _AddException(cms_attribute *attr, time_t time)
347 CSA_date_time_entry *dt, *dlist, *prev;
348 cms_attribute_value *val;
352 if ((dt = (CSA_date_time_entry *)calloc(1, sizeof(CSA_date_time_entry)))
354 return (CSA_E_INSUFFICIENT_MEMORY);
356 if (_csa_tick_to_iso8601(time, buf)) {
358 return (CSA_E_INVALID_DATE_TIME);
359 } else if ((dt->date_time = strdup(buf)) == NULL) {
361 return (CSA_E_INSUFFICIENT_MEMORY);
364 if (attr->value == NULL) {
365 if ((val = (cms_attribute_value *)calloc(1,
366 sizeof(cms_attribute_value))) == NULL) {
369 return (CSA_E_INSUFFICIENT_MEMORY);
372 val->type = CSA_VALUE_DATE_TIME_LIST;
375 if (attr->value->item.date_time_list_value == NULL) {
376 val->item.date_time_list_value = dt;
378 for (dlist = attr->value->item.date_time_list_value, prev=NULL;
380 prev = dlist, dlist = dlist->next) {
381 _csa_iso8601_to_tick(dlist->date_time, &tick);
388 attr->value->item.date_time_list_value = dt;
393 return (CSA_SUCCESS);
397 _TruncateExceptionDates(cms_entry *newe, time_t ltick)
400 CSA_date_time_list dt, prev, head;
402 if (newe->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value == NULL ||
403 newe->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value->item.\
404 date_time_list_value == NULL)
407 head = newe->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value->item.\
408 date_time_list_value;
410 for (dt = head, prev = NULL; dt != NULL; prev = dt, dt = dt->next) {
411 _csa_iso8601_to_tick(dt->date_time, &tick);
415 _DtCm_free_date_time_list(dt);
418 [CSA_ENTRY_ATTR_EXCEPTION_DATES_I].\
420 newe->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].\