Libical API Documentation 4.0 STABLE VERSION [Visit the v3.0 documentation]
Loading...
Searching...
No Matches
icaldirset.c
Go to the documentation of this file.
1/*
2======================================================================
3 FILE: icaldirset.c
4 CREATOR: eric 28 November 1999
5
6 SPDX-FileCopyrightText: 2000, Eric Busboom <eric@civicknowledge.com>
7 SPDX-License-Identifier: LGPL-2.1-only OR MPL-2.0
8
9 The Original Code is eric. The Initial Developer of the Original
10 Code is Eric Busboom
11 ======================================================================*/
12
18
19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
22
23#include "icaldirset.h"
24#include "icaldirsetimpl.h"
25#include "icalerror_p.h"
26#include "icalfileset.h"
27#include "icalpvl_p.h"
28
29#include <stdio.h>
30#include <stdlib.h>
31
32#if defined(HAVE_DIRENT_H)
33#include <dirent.h>
34#endif
35
36#if defined(HAVE_SYS_UTSNAME_H)
37#include <sys/utsname.h>
38#endif
39
41static icaldirset_options icaldirset_options_default = {O_RDWR | O_CREAT};
42
43const char *icaldirset_path(icalset *set)
44{
45 const icaldirset *dset = (icaldirset *)set;
46
47 return dset->dir;
48}
49
50void icaldirset_mark(icalset *set)
51{
52 icaldirset *dset = (icaldirset *)set;
53
54 icalcluster_mark(dset->cluster);
55}
56
58{
59 icaldirset *dset = (icaldirset *)set;
60 icalset *fileset;
62
63 options.cluster = dset->cluster;
64
65 fileset = icalset_new(ICAL_FILE_SET, icalcluster_key(dset->cluster), &options);
66
67 (void)fileset->commit(fileset);
68 fileset->free(fileset);
69
70 return ICAL_NO_ERROR;
71}
72
73static void icaldirset_lock(const char *dir)
74{
75 _unused(dir);
76}
77
78static void icaldirset_unlock(const char *dir)
79{
80 _unused(dir);
81}
82
83/* Load the contents of the store directory into the store's internal directory list*/
84static icalerrorenum icaldirset_read_directory(icaldirset *dset)
85{
86 char *str;
87
88#if defined(HAVE_DIRENT_H)
89 const struct dirent *de;
90 DIR *dp;
91
92 dp = opendir(dset->dir);
93
94 if (dp == 0) {
96 return ICAL_FILE_ERROR;
97 }
98
99 /* clear contents of directory list */
100 while ((str = icalpvl_pop(dset->directory))) {
101 free(str);
102 }
103
104 /* load all of the cluster names in the directory list */
105 for (de = readdir(dp); de != 0; de = readdir(dp)) {
106 /* Remove known directory names '.' and '..' */
107 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) {
108 continue;
109 }
110
111 icalpvl_push(dset->directory, (void *)strdup(de->d_name));
112 }
113
114 closedir(dp);
115#else
116 struct _finddata_t c_file;
117 intptr_t hFile;
118
119 /* Find first .c file in current directory */
120 if ((hFile = _findfirst("*", &c_file)) == -1L) {
122 return ICAL_FILE_ERROR;
123 } else {
124 while ((str = icalpvl_pop(dset->directory))) {
125 free(str);
126 }
127
128 /* load all of the cluster names in the directory list */
129 do {
130 /* Remove known directory names '.' and '..' */
131 if (strcmp(c_file.name, ".") == 0 || strcmp(c_file.name, "..") == 0) {
132 continue;
133 }
134
135 icalpvl_push(dset->directory, (void *)strdup(c_file.name));
136 } while (_findnext(hFile, &c_file) == 0);
137
138 _findclose(hFile);
139 }
140
141#endif
142
143 return ICAL_NO_ERROR;
144}
145
146/* cppcheck-suppress constParameterPointer */
147icalset *icaldirset_init(icalset *set, const char *dir, void *options_in)
148{
149 icaldirset *dset;
150 const icaldirset_options *options = options_in;
151 struct stat sbuf;
152
153 icalerror_check_arg_rz((dir != 0), "dir");
154 icalerror_check_arg_rz((set != 0), "set");
155 dset = (icaldirset *)set;
156
157 if (stat(dir, &sbuf) != 0) {
159 return 0;
160 }
161
162 /* dir is not the name of a direectory */
163 if (!S_ISDIR(sbuf.st_mode)) {
165 return 0;
166 }
167
168 icaldirset_lock(dir);
169
170 dset->dir = (char *)strdup(dir);
171 if (options) {
172 dset->options = *options;
173 }
174 dset->directory = icalpvl_newlist();
175 dset->directory_iterator = 0;
176 dset->gauge = 0;
177 dset->first_component = 0;
178 dset->cluster = 0;
179
180 return set;
181}
182
183icalset *icaldirset_new(const char *dir)
184{
185 return icalset_new(ICAL_DIR_SET, dir, &icaldirset_options_default);
186}
187
188icalset *icaldirset_new_reader(const char *dir)
189{
190 icaldirset_options reader_options = icaldirset_options_default;
191
192 reader_options.flags = O_RDONLY;
193
194 return icalset_new(ICAL_DIR_SET, dir, &reader_options);
195}
196
197icalset *icaldirset_new_writer(const char *dir)
198{
199 icaldirset_options writer_options = icaldirset_options_default;
200
201 writer_options.flags = O_RDWR | O_CREAT;
202
203 return icalset_new(ICAL_DIR_SET, dir, &writer_options);
204}
205
206void icaldirset_free(icalset *s)
207{
208 icaldirset *dset = (icaldirset *)s;
209 char *str;
210
211 icaldirset_unlock(dset->dir);
212
213 if (dset->dir != 0) {
214 free(dset->dir);
215 dset->dir = 0;
216 }
217
218 if (dset->gauge != 0) {
219 icalgauge_free(dset->gauge);
220 dset->gauge = 0;
221 }
222
223 if (dset->cluster != 0) {
224 icalcluster_free(dset->cluster);
225 }
226
227 while (dset->directory != 0 && (str = icalpvl_pop(dset->directory)) != 0) {
228 free(str);
229 }
230
231 if (dset->directory != 0) {
232 icalpvl_free(dset->directory);
233 dset->directory = 0;
234 }
235
236 dset->directory_iterator = 0;
237 dset->first_component = 0;
238}
239
240static icalerrorenum icaldirset_next_cluster(icaldirset *dset)
241{
242 char path[MAXPATHLEN];
243
244 if (dset->directory_iterator == 0) {
246 return ICAL_INTERNAL_ERROR;
247 }
248 dset->directory_iterator = icalpvl_next(dset->directory_iterator);
249
250 if (dset->directory_iterator == 0) {
251 /* There are no more clusters */
252 if (dset->cluster != 0) {
253 icalcluster_free(dset->cluster);
254 dset->cluster = 0;
255 }
256 return ICAL_NO_ERROR;
257 }
258
259 snprintf(path, sizeof(path), "%s/%s", dset->dir, (char *)icalpvl_data(dset->directory_iterator));
260
261 icalcluster_free(dset->cluster);
262 dset->cluster = icalfileset_produce_icalcluster(path);
263
264 return icalerrno;
265}
266
267static void icaldirset_add_uid(icalcomponent *comp)
268{
269 char uidstring[MAXPATHLEN] = {0};
270 icalproperty *uid;
271
272#if defined(HAVE_SYS_UTSNAME_H)
273 struct utsname unamebuf;
274#endif
275
276 icalerror_check_arg_rv((comp != 0), "comp");
277
279
280 if (uid == 0) {
281#if defined(HAVE_SYS_UTSNAME_H)
282 uname(&unamebuf);
283 snprintf(uidstring, sizeof(uidstring), "%d-%s", (int)getpid(), unamebuf.nodename);
284#else
285 /* FIXME: There must be an easy get the system name */
286 snprintf(uidstring, sizeof(uidstring), "%d-%s", (int)getpid(), "WINDOWS");
287#endif
288 uid = icalproperty_new_uid(uidstring);
290 } else {
291 strncpy(uidstring, icalproperty_get_uid(uid), MAXPATHLEN - 1);
292 }
293}
294
295icalerrorenum icaldirset_add_component(icalset *set, icalcomponent *comp)
296{
297 char clustername[MAXPATHLEN] = {0};
298 icalproperty *dt = 0;
299 icalvalue *v;
300 struct icaltimetype tm;
302 icalcomponent *inner;
303 icaldirset *dset;
304
305 icalerror_check_arg_rz((set != 0), "set");
306 icalerror_check_arg_rz((comp != 0), "comp");
307
308 dset = (icaldirset *)set;
309
310 icaldirset_add_uid(comp);
311
312 /* Determine which cluster this object belongs in. This is a HACK */
313
315 inner != 0; inner = icalcomponent_get_next_component(comp, ICAL_ANY_COMPONENT)) {
317
318 if (dt != 0) {
319 break;
320 }
321 }
322
323 if (dt == 0) {
325 inner != 0; inner = icalcomponent_get_next_component(comp, ICAL_ANY_COMPONENT)) {
327
328 if (dt != 0) {
329 break;
330 }
331 }
332 }
333
334 if (dt == 0) {
335 icalerror_warn("The component does not have a DTSTAMP or DTSTART property, "
336 "so it cannot be added to the store");
338 return ICAL_BADARG_ERROR;
339 }
340
343
344 snprintf(clustername, MAXPATHLEN, "%s/%04d%02d", dset->dir, tm.year, tm.month);
345
346 /* Load the cluster and insert the object */
347 if (dset->cluster != 0 && strcmp(clustername, icalcluster_key(dset->cluster)) != 0) {
348 icalcluster_free(dset->cluster);
349 dset->cluster = 0;
350 }
351
352 if (dset->cluster == 0) {
353 dset->cluster = icalfileset_produce_icalcluster(clustername);
354
355 if (dset->cluster == 0) {
356 error = icalerrno;
357 }
358 }
359
360 if (error != ICAL_NO_ERROR) {
361 icalerror_set_errno(error);
362 return error;
363 }
364
365 /* Add the component to the cluster */
366 (void)icalcluster_add_component(dset->cluster, comp);
367
368 /* icalcluster_mark(cluster->cluster); */
369
370 return ICAL_NO_ERROR;
371}
372
373icalerrorenum icaldirset_remove_component(icalset *set, icalcomponent *comp)
374{
375 icaldirset *dset;
376 icalcomponent *filecomp;
377 icalcompiter i;
378 int found = 0;
379
380 icalerror_check_arg_re((set != 0), "set", ICAL_BADARG_ERROR);
381 icalerror_check_arg_re((comp != 0), "comp", ICAL_BADARG_ERROR);
382
383 dset = (icaldirset *)set;
384 icalerror_check_arg_re((dset->cluster != 0), "Cluster pointer", ICAL_USAGE_ERROR);
385
386 filecomp = icalcluster_get_component(dset->cluster);
387
390 const icalcomponent *this = icalcompiter_deref(&i);
391 if (this == comp) {
392 found = 1;
393 break;
394 }
395 }
396
397 if (found != 1) {
398 icalerror_warn("icaldirset_remove_component: component is not part of current cluster");
400 return ICAL_USAGE_ERROR;
401 }
402
403 (void)icalcluster_remove_component(dset->cluster, comp);
404
405 /* icalcluster_mark(cluster->cluster); */
406
407 /* If the removal emptied the fileset, get the next fileset */
408 if (icalcluster_count_components(dset->cluster, ICAL_ANY_COMPONENT) == 0) {
409 icalerrorenum error = icaldirset_next_cluster(dset);
410
411 if (dset->cluster != 0 && error == ICAL_NO_ERROR) {
412 (void)icalcluster_get_first_component(dset->cluster);
413 } else {
414 /* HACK. Not strictly correct for cluster->cluster==0 */
415 return error;
416 }
417 } else {
418 /* Do nothing */
419 }
420
421 return ICAL_NO_ERROR;
422}
423
425{
426 _unused(store);
427 _unused(kind);
428
429 /* NOT IMPLEMENTED */
430 assert(0);
431
432 return 0;
433}
434
435icalcomponent *icaldirset_fetch_match(icalset *set, const icalcomponent *c)
436{
437 _unused(set);
438 _unused(c);
439
440 fprintf(stderr, " icaldirset_fetch_match is not implemented\n");
441 assert(0);
442 return 0;
443}
444
445icalcomponent *icaldirset_fetch(icalset *set, icalcomponent_kind kind, const char *uid)
446{
447 icaldirset *dset;
448 icalgauge *gauge;
449 icalgauge *old_gauge;
450 icalcomponent *c;
451 char sql[256];
452
453 _unused(kind);
454
455 icalerror_check_arg_rz((set != 0), "set");
456 icalerror_check_arg_rz((uid != 0), "uid");
457
458 snprintf(sql, 256, "SELECT * FROM VEVENT WHERE UID = \"%s\"", uid);
459
460 gauge = icalgauge_new_from_sql(sql, 0);
461 dset = (icaldirset *)set;
462 old_gauge = dset->gauge;
463 dset->gauge = gauge;
464
466
467 dset->gauge = old_gauge;
468
469 if (gauge) {
470 icalgauge_free(gauge);
471 }
472
473 return c;
474}
475
476int icaldirset_has_uid(icalset *set, const char *uid)
477{
478 const icalcomponent *c;
479
480 icalerror_check_arg_rz((set != 0), "set");
481 icalerror_check_arg_rz((uid != 0), "uid");
482
483 /* HACK. This is a temporary implementation. _has_uid should use a
484 database, and _fetch should use _has_uid, not the other way
485 around */
486 c = icaldirset_fetch(set, 0, uid);
487
488 return c != 0;
489}
490
491icalerrorenum icaldirset_select(icalset *set, icalgauge *gauge)
492{
493 icaldirset *dset;
494
495 icalerror_check_arg_re((set != 0), "set", ICAL_BADARG_ERROR);
496 icalerror_check_arg_re((gauge != 0), "gauge", ICAL_BADARG_ERROR);
497
498 dset = (icaldirset *)set;
499 dset->gauge = gauge;
500
501 return ICAL_NO_ERROR;
502}
503
504icalerrorenum icaldirset_modify(icalset *set, icalcomponent *oldcomp, icalcomponent *newcomp)
505{
506 _unused(set);
507 _unused(oldcomp);
508 _unused(newcomp);
509
510 /* NOT IMPLEMENTED */
511 assert(0);
512 return ICAL_NO_ERROR;
513}
514
515void icaldirset_clear(icalset *set)
516{
517 _unused(set);
518
519 /* NOT IMPLEMENTED */
520 assert(0);
521}
522
523icalcomponent *icaldirset_get_current_component(icalset *set)
524{
525 icaldirset *dset = (icaldirset *)set;
526
527 icalerror_check_arg_rz((dset != 0), "dset");
528
529 if (dset->cluster == 0) {
531 } else {
532 return icalcluster_get_current_component(dset->cluster);
533 }
534}
535
536icalcomponent *icaldirset_get_first_component(icalset *set)
537{
538 icaldirset *dset = (icaldirset *)set;
539
540 icalerrorenum error;
541 char path[MAXPATHLEN];
542
543 error = icaldirset_read_directory(dset);
544
545 if (error != ICAL_NO_ERROR) {
546 icalerror_set_errno(error);
547 return 0;
548 }
549
550 dset->directory_iterator = icalpvl_head(dset->directory);
551
552 if (dset->directory_iterator == 0) {
553 icalerror_set_errno(error);
554 return 0;
555 }
556
557 snprintf(path, MAXPATHLEN, "%s/%s", dset->dir, (char *)icalpvl_data(dset->directory_iterator));
558
559 /* If the next cluster we need is different than the current cluster,
560 delete the current one and get a new one */
561
562 if (dset->cluster != 0 && strcmp(path, icalcluster_key(dset->cluster)) != 0) {
563 icalcluster_free(dset->cluster);
564 dset->cluster = 0;
565 }
566
567 if (dset->cluster == 0) {
568 dset->cluster = icalfileset_produce_icalcluster(path);
569
570 if (dset->cluster == 0) {
571 error = icalerrno;
572 }
573 }
574
575 if (error != ICAL_NO_ERROR) {
576 icalerror_set_errno(error);
577 return 0;
578 }
579
580 dset->first_component = 1;
581
583}
584
585icalcomponent *icaldirset_get_next_component(icalset *set)
586{
587 icaldirset *dset;
588 icalcomponent *c;
589 icalerrorenum error;
590
591 icalerror_check_arg_rz((set != 0), "set");
592 dset = (icaldirset *)set;
593
594 if (dset->cluster == 0) {
595 icalerror_warn("icaldirset_get_next_component called with a NULL cluster "
596 "(Caller must call icaldirset_get_first_component first)");
598 return 0;
599 }
600
601 /* Set the component iterator for the following for loop */
602 if (dset->first_component == 1) {
603 (void)icalcluster_get_first_component(dset->cluster);
604 dset->first_component = 0;
605 } else {
606 (void)icalcluster_get_next_component(dset->cluster);
607 }
608
609 while (1) {
610 /* Iterate through all of the objects in the cluster */
611 for (c = icalcluster_get_current_component(dset->cluster);
612 c != 0; c = icalcluster_get_next_component(dset->cluster)) {
613 /* If there is a gauge defined and the component does not
614 pass the gauge, skip the rest of the loop */
615
616 if (dset->gauge != 0 && !icalgauge_compare(dset->gauge, c)) {
617 continue;
618 }
619
620 /* Either there is no gauge, or the component passed the
621 gauge, so return it */
622
623 return c;
624 }
625
626 /* Fell through the loop, so the component we want is not
627 in this cluster. Load a new cluster and try again. */
628
629 error = icaldirset_next_cluster(dset);
630
631 if (dset->cluster == 0 || error != ICAL_NO_ERROR) {
632 /* No more clusters */
633 return 0;
634 } else {
635 c = icalcluster_get_first_component(dset->cluster);
636
637 return c;
638 }
639 }
640
641 return 0; /* Should never get here */
642}
643
645 const char *tzid)
646{
647 _unused(set);
648 _unused(kind);
649 _unused(gauge);
650 _unused(tzid);
651 /*
652 icalsetiter itr = icalsetiter_null;
653 icaldirset *fset = (icaldirset*) set;
654
655 icalerror_check_arg_re((fset!=0), "set", icalsetiter_null);
656
657 itr.iter.kind = kind;
658 itr.gauge = gauge;
659 */
660 /* TO BE IMPLEMENTED */
661 return icalsetiter_null;
662}
663
664icalcomponent *icaldirsetiter_to_next(icalset *set, icalsetiter *i)
665{
666 _unused(set);
667 _unused(i);
668 /* TO BE IMPLEMENTED */
669 return NULL;
670}
671
672icalcomponent *icaldirsetiter_to_prior(icalset *set, icalsetiter *i)
673{
674 _unused(set);
675 _unused(i);
676 /* TO BE IMPLEMENTED */
677 return NULL;
678}
icalcomponent * icalcluster_get_current_component(icalcluster *cluster)
Iterate through components.
int icalcluster_count_components(icalcluster *cluster, icalcomponent_kind kind)
const char * icalcluster_key(const icalcluster *cluster)
icalerrorenum icalcluster_add_component(icalcluster *cluster, icalcomponent *child)
icalcomponent * icalcluster_get_component(const icalcluster *cluster)
icalcomponent * icalcluster_get_next_component(icalcluster *cluster)
void icalcluster_free(icalcluster *cluster)
Definition icalcluster.c:84
icalerrorenum icalcluster_remove_component(icalcluster *cluster, icalcomponent *child)
void icalcluster_mark(icalcluster *cluster)
icalcomponent * icalcluster_get_first_component(icalcluster *cluster)
icalproperty * icalcomponent_get_first_property(icalcomponent *c, icalproperty_kind kind)
icalcomponent * icalcompiter_next(icalcompiter *i)
icalcomponent * icalcomponent_get_next_component(icalcomponent *c, icalcomponent_kind kind)
icalcomponent * icalcomponent_get_first_component(icalcomponent *c, icalcomponent_kind kind)
icalcomponent * icalcompiter_deref(icalcompiter *i)
void icalcomponent_add_property(icalcomponent *component, icalproperty *property)
icalcompiter icalcomponent_begin_component(icalcomponent *component, icalcomponent_kind kind)
const char * icalproperty_get_uid(const icalproperty *prop)
icalproperty * icalproperty_new_uid(const char *v)
@ ICAL_UID_PROPERTY
@ ICAL_DTSTAMP_PROPERTY
@ ICAL_DTSTART_PROPERTY
struct icaltimetype icalvalue_get_datetime(const icalvalue *value)
struct icalvalue_impl icalvalue
icalerrorenum icaldirset_add_component(icalset *set, icalcomponent *comp)
Definition icaldirset.c:295
icalsetiter icaldirset_begin_component(icalset *set, icalcomponent_kind kind, icalgauge *gauge, const char *tzid)
Definition icaldirset.c:644
icalcomponent * icaldirset_fetch(icalset *set, icalcomponent_kind kind, const char *uid)
Definition icaldirset.c:445
icalset * icaldirset_init(icalset *set, const char *dir, void *options_in)
Definition icaldirset.c:147
icalcomponent * icaldirset_get_current_component(icalset *set)
Definition icaldirset.c:523
int icaldirset_has_uid(icalset *set, const char *uid)
Definition icaldirset.c:476
icalset * icaldirset_new_reader(const char *dir)
Definition icaldirset.c:188
icalerrorenum icaldirset_commit(icalset *set)
Definition icaldirset.c:57
void icaldirset_clear(icalset *set)
Definition icaldirset.c:515
icalerrorenum icaldirset_modify(icalset *set, icalcomponent *oldcomp, icalcomponent *newcomp)
Definition icaldirset.c:504
icalcomponent * icaldirset_fetch_match(icalset *set, const icalcomponent *c)
Definition icaldirset.c:435
icalcomponent * icaldirset_get_next_component(icalset *set)
Definition icaldirset.c:585
const char * icaldirset_path(icalset *set)
Definition icaldirset.c:43
void icaldirset_mark(icalset *set)
Definition icaldirset.c:50
icalerrorenum icaldirset_remove_component(icalset *set, icalcomponent *comp)
Definition icaldirset.c:373
icalset * icaldirset_new(const char *dir)
Definition icaldirset.c:183
icalset * icaldirset_new_writer(const char *dir)
Definition icaldirset.c:197
icalerrorenum icaldirset_select(icalset *set, icalgauge *gauge)
Definition icaldirset.c:491
icalcomponent * icaldirset_get_first_component(icalset *set)
Definition icaldirset.c:536
icalcomponent * icaldirsetiter_to_next(icalset *set, icalsetiter *i)
Definition icaldirset.c:664
icalcomponent * icaldirsetiter_to_prior(icalset *set, icalsetiter *i)
Definition icaldirset.c:672
void icaldirset_free(icalset *s)
Definition icaldirset.c:206
int icaldirset_count_components(icalset *store, icalcomponent_kind kind)
Definition icaldirset.c:424
Manages a database of ical components and offers interfaces for reading, writing and searching for co...
struct icaldirset_impl icaldirset
Definition icaldirset.h:46
enum icalrequeststatus kind
Definition icalenums.c:26
const char * str
Definition icalenums.c:29
icalcomponent_kind
Definition icalenums.h:29
@ ICAL_ANY_COMPONENT
Definition icalenums.h:31
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:42
@ ICAL_BADARG_ERROR
Definition icalerror.h:47
@ ICAL_FILE_ERROR
Definition icalerror.h:68
@ ICAL_INTERNAL_ERROR
Definition icalerror.h:65
@ ICAL_NO_ERROR
Definition icalerror.h:44
@ ICAL_USAGE_ERROR
Definition icalerror.h:71
#define icalerrno
Access the current icalerrno value.
Definition icalerror.h:133
icalcluster * icalfileset_produce_icalcluster(const char *path)
icalfileset_options icalfileset_options_default
Definition icalfileset.c:42
Manages a database of ical components and offers interfaces for reading, writing and searching for co...
bool icalgauge_compare(icalgauge *gauge, icalcomponent *comp)
Definition icalgauge.c:216
void icalgauge_free(icalgauge *gauge)
Definition icalgauge.c:72
icalgauge * icalgauge_new_from_sql(const char *sql, int expand)
Definition icalgauge.c:38
icalvalue * icalproperty_get_value(const icalproperty *prop)
icalsetiter icalsetiter_null
Definition icalset.c:413
icalset * icalset_new(icalset_kind kind, const char *dsn, void *options)
Definition icalset.c:193
@ ICAL_FILE_SET
Definition icalset.h:39
@ ICAL_DIR_SET
Definition icalset.h:40
Options for opening an icalfileset.
icalcluster * cluster