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>
41 #if !defined(CSRG_BASED)
45 #include <sys/systeminfo.h>
47 #include "cmscalendar.h"
63 /******************************************************************************
64 * forward declaration of static functions used within the file
65 ******************************************************************************/
66 static boolean_t _InSequence(List_node *node, time_t time);
67 static CSA_return_code _AddException(cms_attribute *attr, time_t time);
68 static CSA_return_code _AddEndDateToRule(cms_attribute *attr, RepeatEvent *re,
70 static void _TruncateExceptionDates(cms_entry *newe, time_t ltick);
72 /*****************************************************************************
73 * extern functions used in the library
74 *****************************************************************************/
76 extern CSA_return_code
86 List_node *lnode = NULL;
89 if ((entry = (cms_entry *)rb_lookup(cal->tree, (caddr_t)key)) == NULL) {
90 /* find entry in the repeating entry list */
91 if ((lnode = hc_lookup_node(cal->list, (caddr_t)key)) == NULL)
92 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
94 entry = (cms_entry *)lnode->data;
98 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
100 if (sender && (stat = _DtCmsCheckChangeAccess(sender, access, entry))
105 if ((tnode = rb_delete(cal->tree, (caddr_t)key)) != NULL) {
106 _DtCmsObsoleteReminder4Entry(cal->remq, entry, NULL,
110 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
112 _DtCmsObsoleteReminder4Entry(cal->remq, entry, lnode,
114 hc_delete_node(cal->list, lnode);
122 _DtCm_free_cms_entry(entry);
124 return (CSA_SUCCESS);
127 extern CSA_return_code
128 _DtCmsDeleteEntryAndLog(
135 CSA_return_code stat;
138 if ((stat = _DtCmsDeleteEntry(cal, sender, access, key, &entry))
140 if ((stat = _DtCmsV5TransactLog(cal, entry, _DtCmsLogRemove))
142 (void)_DtCmsInsertEntry(cal, entry);
143 _DtCm_free_cms_entry(entry);
147 _DtCm_free_cms_entry(entry);
153 extern CSA_return_code
154 _DtCmsDeleteInstancesAndLog(
163 CSA_return_code stat;
164 cms_entry *entry, *nentry;
168 cms_attribute *tmp_attrs, *aptr;
169 boolean_t delentry = B_FALSE;
171 if ((lnode = hc_lookup_node(cal->list, (caddr_t)key)) == NULL)
172 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
174 entry = (cms_entry *)lnode->data;
176 if ((stat = _DtCmsCheckChangeAccess(sender, access, entry))
180 if (_DtCmsInExceptionList(entry, key->time) ||
181 !_InSequence(lnode, key->time))
182 return (CSA_X_DT_E_ENTRY_NOT_FOUND);
184 if ((stat = _DtCm_copy_cms_entry(entry, &nentry)) != CSA_SUCCESS)
187 if (scope == CSA_SCOPE_ONE)
188 stat = _AddException(
189 &nentry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I],
192 /* check whether we are deleting from fst instance */
193 if (key->time == nentry->key.time)
196 stat = _DtCmsAddEndDateToRule(&nentry->attrs\
197 [CSA_ENTRY_ATTR_RECURRENCE_RULE_I],
198 lnode->re, key->time - 1);
199 lnode->re->re_end_date = key->time - 1;
201 _TruncateExceptionDates(nentry, key->time);
205 if (stat != CSA_SUCCESS) {
206 _DtCm_free_cms_entry(nentry);
211 if ((stat = _DtCmsSetLastUpdate(nentry)) != SUCCESS) {
212 _DtCm_free_cms_entry(nentry);
216 /* remove original entry from log */
217 if ((stat = _DtCmsGetFileSize(cal->calendar, &fsize))
219 _DtCm_free_cms_entry(nentry);
223 if ((stat = _DtCmsV5TransactLog(cal, entry, _DtCmsLogRemove))
225 _DtCm_free_cms_entry(nentry);
229 aptr = &nentry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I];
230 count = CountEvents(nentry->key.time, lnode->re, (aptr->value ?
231 aptr->value->item.date_time_list_value : NULL));
234 if (count == 0 || delentry) {
236 * *** obsolete reminders
238 _DtCmsObsoleteReminder4Entry(cal->remq, entry, lnode,
241 hc_delete_node(cal->list, lnode);
244 _DtCm_free_cms_entry(nentry);
249 _DtCm_free_cms_entry(entry);
255 /* add new entry in memory and log in file */
257 /* update the count */
260 _DtCmsConvertToOnetime(nentry, lnode->re);
261 stat = _DtCmsRbToCsaStat(rb_insert(cal->tree,
262 (caddr_t)nentry, (caddr_t)&(nentry->key)));
264 } else if (count != RE_INFINITY) {
265 nentry->attrs[CSA_ENTRY_ATTR_NUMBER_RECURRENCES_I].\
266 value->item.uint32_value = count;
269 /* the new entry should be copied when it's updated
272 if (stat == CSA_SUCCESS && newe)
273 stat = _DtCm_copy_cms_entry(nentry, newe);
275 if (stat || (stat = _DtCmsV5TransactLog(cal, nentry,
276 _DtCmsLogAdd)) != CSA_SUCCESS) {
277 _DtCmsTruncateFile(cal->calendar, fsize);
278 _DtCm_free_cms_entry(nentry);
279 if (newe) free(*newe);
282 _DtCmsObsoleteReminder4Entry(cal->remq, entry,
284 hc_delete_node(cal->list, lnode);
286 _DtCmsAddReminders4Entry(&cal->remq, nentry, NULL);
288 /* need to do the swap since the original entry
289 * pointer is stored in the reminder info
291 tmp_num = entry->num_attrs;
292 tmp_attrs = entry->attrs;
293 entry->num_attrs = nentry->num_attrs;
294 entry->attrs = nentry->attrs;
295 nentry->num_attrs = tmp_num;
296 nentry->attrs = tmp_attrs;
298 _DtCmsObsoleteReminder4Entry(cal->remq, entry,
300 (scope == CSA_SCOPE_ONE ? B_FALSE :
303 if (scope == CSA_SCOPE_FORWARD ||
304 key->time == lnode->lasttick) {
305 lnode->lasttick = LastTick(
312 *olde = (count == 1) ? entry : nentry;
314 _DtCm_free_cms_entry((count==1)?entry:nentry);
321 /*****************************************************************************
322 * static functions used within the file
323 *****************************************************************************/
326 _InSequence(List_node *node, time_t time)
329 cms_entry *entry = (cms_entry *)node->data;
330 RepeatEventState *restate;
332 for (tick = ClosestTick(time, entry->key.time, node->re, &restate);
333 tick <= node->lasttick;
334 tick = NextTick(tick, entry->key.time, node->re, restate))
336 if (tick <= 0 || tick > node->lasttick)
346 static CSA_return_code
347 _AddException(cms_attribute *attr, time_t time)
349 CSA_date_time_entry *dt, *dlist, *prev;
350 cms_attribute_value *val;
354 if ((dt = (CSA_date_time_entry *)calloc(1, sizeof(CSA_date_time_entry)))
356 return (CSA_E_INSUFFICIENT_MEMORY);
358 if (_csa_tick_to_iso8601(time, buf)) {
360 return (CSA_E_INVALID_DATE_TIME);
361 } else if ((dt->date_time = strdup(buf)) == NULL) {
363 return (CSA_E_INSUFFICIENT_MEMORY);
366 if (attr->value == NULL) {
367 if ((val = (cms_attribute_value *)calloc(1,
368 sizeof(cms_attribute_value))) == NULL) {
371 return (CSA_E_INSUFFICIENT_MEMORY);
374 val->type = CSA_VALUE_DATE_TIME_LIST;
377 if (attr->value->item.date_time_list_value == NULL) {
378 val->item.date_time_list_value = dt;
380 for (dlist = attr->value->item.date_time_list_value, prev=NULL;
382 prev = dlist, dlist = dlist->next) {
383 _csa_iso8601_to_tick(dlist->date_time, &tick);
390 attr->value->item.date_time_list_value = dt;
395 return (CSA_SUCCESS);
399 _TruncateExceptionDates(cms_entry *newe, time_t ltick)
402 CSA_date_time_list dt, prev, head;
404 if (newe->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value == NULL ||
405 newe->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value->item.\
406 date_time_list_value == NULL)
409 head = newe->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value->item.\
410 date_time_list_value;
412 for (dt = head, prev = NULL; dt != NULL; prev = dt, dt = dt->next) {
413 _csa_iso8601_to_tick(dt->date_time, &tick);
417 _DtCm_free_date_time_list(dt);
420 [CSA_ENTRY_ATTR_EXCEPTION_DATES_I].\
422 newe->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].\