$darkmode
Libical API Documentation 4.0 STABLE VERSION Visit the v3.0 documentation
icalset.c
Go to the documentation of this file.
1 /*======================================================================
2  FILE: icalset.c
3  CREATOR: eric 17 Jul 2000
4 
5  SPDX-FileCopyrightText: 2000, Eric Busboom <eric@civicknowledge.com>
6  SPDX-License-Identifier: LGPL-2.1-only OR MPL-2.0
7 
8  Icalset is the "base class" for representations of a collection of
9  iCal components. Derived classes (actually delegates) include:
10 
11  icalfileset Store components in a single file
12  icaldirset Store components in multiple files in a directory
13  icalheapset Store components on the heap
14  icalmysqlset Store components in a mysql database.
15 
16  The Original Code is eric. The Initial Developer of the Original
17  Code is Eric Busboom
18 ======================================================================*/
19 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include "icalset.h"
30 #include "icaldirset.h"
31 #include "icaldirsetimpl.h"
32 #include "icalerror_p.h"
33 #include "icalfileset.h"
34 #include "icalfilesetimpl.h"
35 
36 #if defined(HAVE_BDB)
37 #include "icalbdbset.h"
38 #include "icalbdbsetimpl.h"
39 #endif
40 
41 #include <errno.h>
42 #include <stdlib.h>
43 
44 /* #define _DLOPEN_TEST */
45 #if defined(_DLOPEN_TEST)
46 #include <sys/types.h>
47 #include <dlfcn.h>
48 #include <dirent.h>
49 #endif
50 
51 static icalset icalset_dirset_init = {
53  sizeof(icaldirset),
54  NULL,
55  icaldirset_init,
56  icaldirset_free,
57  icaldirset_path,
58  icaldirset_mark,
59  icaldirset_commit,
62  icaldirset_count_components,
63  icaldirset_select,
64  icaldirset_clear,
65  icaldirset_fetch,
66  icaldirset_fetch_match,
67  icaldirset_has_uid,
68  icaldirset_modify,
69  icaldirset_get_current_component,
70  icaldirset_get_first_component,
71  icaldirset_get_next_component,
72  icaldirset_begin_component,
73  icaldirsetiter_to_next,
74  icaldirsetiter_to_prior};
75 
76 static icalset icalset_fileset_init = {
78  sizeof(icalfileset),
79  NULL,
80  icalfileset_init,
81  icalfileset_free,
82  icalfileset_path,
83  icalfileset_mark,
84  icalfileset_commit,
85  icalfileset_add_component,
86  icalfileset_remove_component,
87  icalfileset_count_components,
91  icalfileset_fetch_match,
92  icalfileset_has_uid,
94  icalfileset_get_current_component,
95  icalfileset_get_first_component,
96  icalfileset_get_next_component,
97  icalfileset_begin_component,
98  icalfilesetiter_to_next,
99  NULL};
100 
101 #if defined(HAVE_BDB)
102 static icalset icalset_bdbset_init = {
103  ICAL_BDB_SET,
104  sizeof(icalbdbset),
105  NULL,
106  icalbdbset_init,
107  icalbdbset_free,
109  icalbdbset_mark,
111  icalbdbset_add_component,
112  icalbdbset_remove_component,
113  icalbdbset_count_components,
116  icalbdbset_fetch,
117  icalbdbset_fetch_match,
118  icalbdbset_has_uid,
119  icalbdbset_modify,
121  icalbdbset_get_first_component,
122  icalbdbset_get_next_component,
123  icalbdbset_begin_component,
124  icalbdbsetiter_to_next,
125  NULL};
126 #endif
127 
128 #if defined(_DLOPEN_TEST)
129 static int icalset_init_done = 0;
130 static icalpvl_list icalset_kinds = 0;
131 
132 typedef icalset *(*fptr)(void);
133 
137 static bool load(const char *file)
138 {
139  void *modh;
140  fptr inith;
141  const char *dlerr;
142  icalset *icalset_init_ptr;
143 
144  if ((modh = dlopen(file, RTLD_NOW)) == 0) {
145  perror("dlopen");
146  return false;
147  }
148 
149  (void)dlerror(); /* clear */
150  inith = (fptr)dlsym(modh, "InitModule");
151  dlerr = dlerror();
152  if (dlerr != NULL) {
153  fprintf(stderr, "dlsym error: %s\n", dlerr);
154  dlclose(modh);
155  return false;
156  }
157 
158  while ((icalset_init_ptr = ((inith)())) != 0) {
159  icalpvl_push(icalset_kinds, &icalset_init_ptr);
160  }
161 
162  (void)dlerror(); /* clear */
163  dlclose(modh);
164  return true;
165 }
166 
167 static void icalset_init(void)
168 {
169  assert(icalset_kinds == 0);
170  icalset_kinds = icalpvl_newlist();
171 
172  icalpvl_push(icalset_kinds, &icalset_fileset_init);
173  icalpvl_push(icalset_kinds, &icalset_dirset_init);
174 #if defined(HAVE_BDB)
175  icalpvl_push(icalset_kinds, &icalset_bdb4set_init);
176 #endif
177 
178  icalset_init_done++;
179 }
180 
181 bool icalset_register_class(icalset *set)
182 {
183  if (!icalset_init_done) {
184  icalset_init();
185  }
186 
187  icalpvl_push(icalset_kinds, set);
188  return true;
189 }
190 
191 #endif
192 
193 icalset *icalset_new(icalset_kind kind, const char *dsn, void *options)
194 {
195  icalset *data = NULL;
196  icalset *ret = NULL;
197 
198 #if defined(_DLOPEN_TEST)
199  icalpvl_elem e;
200  const icalset *impl;
201 
202  if (!icalset_init_done) {
203  icalset_init();
204  }
205 
206  for (e = icalpvl_head(icalset_kinds); e != 0; e = icalpvl_next(e)) {
207  impl = (icalset *)icalpvl_data(e);
208  if (impl->kind == kind) {
209  break;
210  }
211  }
212  if (e == 0) {
214  return (NULL);
215  }
216 
217  data = (icalset *)malloc(impl->size);
218  if (data == (icalset *)NULL) {
220  errno = ENOMEM;
221  return 0;
222  }
223 
224  /* The first member of the derived class must be an icalset. */
225  memset(data, 0, impl->size);
226  /* *data = *impl; */
227  memcpy(data, impl, sizeof(icalset));
228 
229  data->dsn = strdup(dsn);
230 #else
231  switch (kind) {
232  case ICAL_FILE_SET: {
233  icalfileset *fdata;
234  fdata = (icalfileset *)malloc(sizeof(icalfileset));
235  data = (icalset *)fdata;
236  if (data == 0) {
238  errno = ENOMEM;
239  return 0;
240  }
241  memset(data, 0, sizeof(icalfileset));
242  *data = icalset_fileset_init;
243  break;
244  }
245  case ICAL_DIR_SET: {
246  icaldirset *ddata;
247  ddata = (icaldirset *)malloc(sizeof(icaldirset));
248  data = (icalset *)ddata;
249  if (data == 0) {
251  errno = ENOMEM;
252  return 0;
253  }
254  memset(data, 0, sizeof(icaldirset));
255  *data = icalset_dirset_init;
256  break;
257  }
258 #if defined(HAVE_BDB)
259  case ICAL_BDB_SET: {
260  icalbdbset *bdata;
261  bdata = (icalbdbset *)malloc(sizeof(icalbdbset));
262  data = (icalset *)bdata;
263  if (data == 0) {
265  errno = ENOMEM;
266  return 0;
267  }
268  memset(data, 0, sizeof(icalbdbset));
269  *data = icalset_bdbset_init;
270  break;
271  }
272 #endif
273 
274  default:
277  return (NULL);
278  }
279 
280  data->kind = kind;
281  data->dsn = strdup(dsn);
282 #endif
283 
285  if ((ret = data->init(data, dsn, options)) == NULL) {
286  /* coverity[alloc_free_mismatch] */
287  icalset_free(data);
288  }
289 
290  return ret;
291 }
292 
293 icalset *icalset_new_file(const char *path)
294 {
295  return icalset_new(ICAL_FILE_SET, path, NULL);
296 }
297 
298 icalset *icalset_new_file_writer(const char *path)
299 {
300  return icalfileset_new_writer(path);
301 }
302 
303 icalset *icalset_new_file_reader(const char *path)
304 {
305  return icalfileset_new_reader(path);
306 }
307 
308 icalset *icalset_new_dir(const char *path)
309 {
310  return icalset_new(ICAL_DIR_SET, path, NULL);
311 }
312 
313 icalset *icalset_new_dir_writer(const char *path)
314 {
315  return icaldirset_new_writer(path);
316 }
317 
318 icalset *icalset_new_dir_reader(const char *path)
319 {
320  return icaldirset_new_reader(path);
321 }
322 
323 /* Functions for built-in methods */
324 
325 void icalset_free(icalset *set)
326 {
327  if (set->free) {
328  set->free(set);
329  }
330 
331  if (set->dsn) {
332  free(set->dsn);
333  }
334 
335  free(set);
336 }
337 
338 const char *icalset_path(icalset *set)
339 {
340  return set->path(set);
341 }
342 
343 void icalset_mark(icalset *set)
344 {
345  set->mark(set);
346 }
347 
349 {
350  return set->commit(set);
351 }
352 
353 icalerrorenum icalset_add_component(icalset *set, icalcomponent *comp)
354 {
355  return set->add_component(set, comp);
356 }
357 
358 icalerrorenum icalset_remove_component(icalset *set, icalcomponent *comp)
359 {
360  return set->remove_component(set, comp);
361 }
362 
363 int icalset_count_components(icalset *set, icalcomponent_kind kind)
364 {
365  return set->count_components(set, kind);
366 }
367 
368 icalerrorenum icalset_select(icalset *set, icalgauge *gauge)
369 {
370  return set->select(set, gauge);
371 }
372 
373 void icalset_clear(icalset *set)
374 {
375  set->clear(set);
376 }
377 
378 icalcomponent *icalset_fetch(icalset *set, const char *uid)
379 {
380  return set->fetch(set, 0, uid);
381 }
382 
383 icalcomponent *icalset_fetch_match(icalset *set, const icalcomponent *comp)
384 {
385  return set->fetch_match(set, comp);
386 }
387 
388 int icalset_has_uid(icalset *set, const char *uid)
389 {
390  return set->has_uid(set, uid);
391 }
392 
393 icalerrorenum icalset_modify(icalset *set, icalcomponent *old, icalcomponent *new)
394 {
395  return set->modify(set, old, new);
396 }
397 
398 icalcomponent *icalset_get_current_component(icalset *set)
399 {
400  return set->get_current_component(set);
401 }
402 
403 icalcomponent *icalset_get_first_component(icalset *set)
404 {
405  return set->get_first_component(set);
406 }
407 
408 icalcomponent *icalset_get_next_component(icalset *set)
409 {
410  return set->get_next_component(set);
411 }
412 
414 
415 icalsetiter icalset_begin_component(icalset *set,
416  icalcomponent_kind kind, icalgauge *gauge, const char *tzid)
417 {
418  return set->icalset_begin_component(set, kind, gauge, tzid);
419 }
420 
421 icalcomponent *icalsetiter_next(icalsetiter *itr)
422 {
423  icalcomponent *c = 0;
424 
425  icalerror_check_arg_rz((itr != NULL), "i");
426 
427  do {
428  c = icalcompiter_next(&(itr->iter));
429  if (c != 0 && (itr->gauge == 0 || icalgauge_compare(itr->gauge, c) == 1)) {
430  return c;
431  }
432  } while (c != 0);
433 
434  return 0;
435 }
436 
437 icalcomponent *icalsetiter_prior(icalsetiter *i)
438 {
439  icalcomponent *c = 0;
440 
441  icalerror_check_arg_rz((i != NULL), "i");
442 
443  do {
444  c = icalcompiter_prior(&(i->iter));
445  if (c != 0 && (i->gauge == 0 || icalgauge_compare(i->gauge, c) == 1)) {
446  return c;
447  }
448  } while (c != 0);
449 
450  return 0;
451 }
452 
453 icalcomponent *icalsetiter_deref(icalsetiter *i)
454 {
455  icalerror_check_arg_rz((i != NULL), "i");
456  return (icalcompiter_deref(&(i->iter)));
457 }
458 
459 /* For subclasses that use multiple clusters that require specialized cluster traversal */
460 icalcomponent *icalsetiter_to_next(icalset *set, icalsetiter *i)
461 {
462  return set->icalsetiter_to_next(set, i);
463 }
464 
465 icalcomponent *icalsetiter_to_prior(icalset *set, icalsetiter *i)
466 {
467  return set->icalsetiter_to_prior(set, i);
468 }
icalcomponent * icalcompiter_prior(icalcompiter *i)
bool icalset_register_class(icalset *set)
icalerrorenum icalfileset_select(icalset *set, icalgauge *gauge)
Definition: icalfileset.c:475
void icalset_mark(icalset *set)
Definition: icalset.c:343
Icalset is the "base class" for representations of a collection of iCal components.
bool icalgauge_compare(icalgauge *gauge, icalcomponent *comp)
Definition: icalgauge.c:216
icalcomponent * icalcompiter_next(icalcompiter *i)
icalerrorenum icaldirset_add_component(icalset *set, icalcomponent *comp)
Definition: icaldirset.c:293
Manages a database of ical components and offers interfaces for reading, writing and searching for co...
icalcomponent * icalset_fetch(icalset *set, const char *uid)
Definition: icalset.c:378
void icalbdbset_clear(icalset *set)
Definition: icalbdbset.c:1000
icalsetiter icalsetiter_null
Definition: icalset.c:413
icalcomponent * icalsetiter_to_next(icalset *set, icalsetiter *i)
Definition: icalset.c:460
void icalerror_set_errno(icalerrorenum x)
Sets the icalerrno to a given error.
Definition: icalerror.c:90
icalerrorenum
Represents the different types of errors that can be triggered in libical.
Definition: icalerror.h:41
icalerrorenum icalbdbset_select(icalset *set, icalgauge *gauge)
Definition: icalbdbset.c:986
icalcomponent * icalsetiter_next(icalsetiter *itr)
Definition: icalset.c:421
icalcomponent * icalset_get_current_component(icalset *set)
Definition: icalset.c:398
icalerrorenum icalset_commit(icalset *set)
Definition: icalset.c:348
void icalfileset_clear(icalset *set)
Clears the gauge.
Definition: icalfileset.c:487
icalset_kind
Definition: icalset.h:37
icalerrorenum icalfileset_modify(icalset *set, icalcomponent *old, icalcomponent *new)
Modifies components according to the MODIFY method of CAP.
Definition: icalfileset.c:648
Manages a database of ical components and offers interfaces for reading, writing and searching for co...
icalcomponent * icalfileset_fetch(icalset *set, icalcomponent_kind kind, const char *uid)
Gets and searches for a component by uid.
Definition: icalfileset.c:497
const char * icalbdbset_path(icalset *set)
Definition: icalbdbset.c:684
icalerrorenum icalset_modify(icalset *set, icalcomponent *old, icalcomponent *new)
Definition: icalset.c:393
icalcomponent_kind
Definition: icalenums.h:28
icalcomponent * icalcompiter_deref(icalcompiter *i)
icalerrorenum icalset_select(icalset *set, icalgauge *gauge)
Definition: icalset.c:368
icalcomponent * icalbdbset_get_current_component(icalset *set)
Definition: icalbdbset.c:1205
icalcomponent * icalset_get_first_component(icalset *set)
Definition: icalset.c:403
icalerrorenum icalbdbset_commit(icalset *set)
Definition: icalbdbset.c:703
icalset * icalset_new(icalset_kind kind, const char *dsn, void *options)
Definition: icalset.c:193
Manages a Berkeley database of ical components and offers interfaces for reading, writing and searchi...
icalcomponent * icalset_get_next_component(icalset *set)
Definition: icalset.c:408
void icalset_free(icalset *set)
Definition: icalset.c:325
icalerrorenum icaldirset_remove_component(icalset *set, icalcomponent *comp)
Definition: icaldirset.c:371