summaryrefslogtreecommitdiffabout
path: root/libical/src/libicalss/icalfileset.c
Unidiff
Diffstat (limited to 'libical/src/libicalss/icalfileset.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libical/src/libicalss/icalfileset.c659
1 files changed, 659 insertions, 0 deletions
diff --git a/libical/src/libicalss/icalfileset.c b/libical/src/libicalss/icalfileset.c
new file mode 100644
index 0000000..943071d
--- a/dev/null
+++ b/libical/src/libicalss/icalfileset.c
@@ -0,0 +1,659 @@
1/* -*- Mode: C -*-
2 ======================================================================
3 FILE: icalfileset.c
4 CREATOR: eric 23 December 1999
5
6 $Id$
7 $Locker$
8
9 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of either:
13
14 The LGPL as published by the Free Software Foundation, version
15 2.1, available at: http://www.fsf.org/copyleft/lesser.html
16
17 Or:
18
19 The Mozilla Public License Version 1.0. You may obtain a copy of
20 the License at http://www.mozilla.org/MPL/
21
22 The Original Code is eric. The Initial Developer of the Original
23 Code is Eric Busboom
24
25
26 ======================================================================*/
27
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <errno.h>
34
35#include <stdlib.h>
36#include <stdio.h>
37#include <string.h>
38
39#include <fcntl.h> /* For open() flags and mode */
40#include <sys/types.h> /* For open() flags and mode */
41#include <sys/stat.h> /* For open() flags and mode */
42
43#include "icalfileset.h"
44#include "icalfilesetimpl.h"
45
46// Eugen C. <eug@thekompany.com>
47#include <defines.h>
48//
49
50int snprintf(char *str, size_t n, char const *fmt, ...);
51
52//extern int errno;
53
54int icalfileset_lock(icalfileset *cluster);
55int icalfileset_unlock(icalfileset *cluster);
56icalerrorenum icalfileset_read_file(icalfileset* cluster, mode_t mode);
57int icalfileset_filesize(icalfileset* cluster);
58
59icalerrorenum icalfileset_create_cluster(const char *path);
60
61icalfileset* icalfileset_new_impl()
62{
63 struct icalfileset_impl* impl;
64
65 if ( ( impl = (struct icalfileset_impl*)
66 malloc(sizeof(struct icalfileset_impl))) == 0) {
67 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
68 errno = ENOMEM;
69 return 0;
70 }
71
72 memset(impl,0,sizeof(struct icalfileset_impl));
73
74 strcpy(impl->id,ICALFILESET_ID);
75
76 return impl;
77}
78
79
80icalfileset* icalfileset_new(const char* path)
81{
82 return icalfileset_new_open(path, O_RDWR|O_CREAT, 0664);
83}
84
85icalfileset* icalfileset_new_open(const char* path, int flags, mode_t mode)
86{
87 struct icalfileset_impl *impl = icalfileset_new_impl();
88 struct icaltimetype tt;
89 off_t cluster_file_size;
90
91 memset(&tt,0,sizeof(struct icaltimetype));
92
93 icalerror_clear_errno();
94 icalerror_check_arg_rz( (path!=0), "path");
95
96 if (impl == 0){
97 return 0;
98 }
99
100 impl->path = strdup(path);
101
102 cluster_file_size = icalfileset_filesize(impl);
103
104 if(cluster_file_size < 0){
105 icalfileset_free(impl);
106 return 0;
107 }
108
109 impl->fd = open(impl->path,flags, mode);
110
111 if (impl->fd < 0){
112 icalerror_set_errno(ICAL_FILE_ERROR);
113 icalfileset_free(impl);
114 return 0;
115 }
116
117 icalfileset_lock(impl);
118
119 if(cluster_file_size > 0 ){
120 icalerrorenum error;
121 if((error = icalfileset_read_file(impl,mode))!= ICAL_NO_ERROR){
122 icalfileset_free(impl);
123 return 0;
124 }
125 }
126
127 if(impl->cluster == 0){
128 impl->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT);
129 }
130
131 return impl;
132}
133
134char* icalfileset_read_from_file(char *s, size_t size, void *d)
135{
136
137 char* p = s;
138 int fd = (int)d;
139
140 /* Simulate fgets -- read single characters and stop at '\n' */
141
142 for(p=s; p<s+size-1;p++){
143
144 if(read(fd,p,1) != 1 || *p=='\n'){
145 p++;
146 break;
147 }
148 }
149
150 *p = '\0';
151
152 if(*s == 0){
153 return 0;
154 } else {
155 return s;
156 }
157
158}
159
160
161icalerrorenum icalfileset_read_file(icalfileset* cluster,mode_t mode)
162{
163
164 icalparser *parser;
165
166 struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
167
168 parser = icalparser_new();
169 icalparser_set_gen_data(parser,(void*)impl->fd);
170 impl->cluster = icalparser_parse(parser,icalfileset_read_from_file);
171 icalparser_free(parser);
172
173 if (impl->cluster == 0 || icalerrno != ICAL_NO_ERROR){
174 icalerror_set_errno(ICAL_PARSE_ERROR);
175 return ICAL_PARSE_ERROR;
176 }
177
178 if (icalcomponent_isa(impl->cluster) != ICAL_XROOT_COMPONENT){
179 /* The parser got a single component, so it did not put it in
180 an XROOT. */
181 icalcomponent *cl = impl->cluster;
182 impl->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT);
183 icalcomponent_add_component(impl->cluster,cl);
184 }
185
186 return ICAL_NO_ERROR;
187
188}
189
190int icalfileset_filesize(icalfileset* cluster)
191{
192 struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
193 int cluster_file_size;
194 struct stat sbuf;
195
196 if (stat(impl->path,&sbuf) != 0){
197
198 /* A file by the given name does not exist, or there was
199 another error */
200 cluster_file_size = 0;
201 if (errno == ENOENT) {
202 /* It was because the file does not exist */
203 return 0;
204 } else {
205 /* It was because of another error */
206 icalerror_set_errno(ICAL_FILE_ERROR);
207 return -1;
208 }
209 } else {
210 /* A file by the given name exists, but is it a regular file? */
211
212#ifndef _QTWIN_
213 if (!S_ISREG(sbuf.st_mode)){
214 /* Nope, not a regular file */
215 icalerror_set_errno(ICAL_FILE_ERROR);
216 return -1;
217 } else {
218 /* Lets assume that it is a file of the right type */
219 return sbuf.st_size;
220 }
221#else
222 return sbuf.st_size;
223#endif
224
225 }
226
227 /*return -1; not reached*/
228}
229
230void icalfileset_free(icalfileset* cluster)
231{
232 struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
233
234 icalerror_check_arg_rv((cluster!=0),"cluster");
235
236 if (impl->cluster != 0){
237 icalfileset_commit(cluster);
238 icalcomponent_free(impl->cluster);
239 impl->cluster=0;
240 }
241
242 if(impl->fd > 0){
243 icalfileset_unlock(impl);
244 close(impl->fd);
245 impl->fd = -1;
246 }
247
248 if(impl->path != 0){
249 free(impl->path);
250 impl->path = 0;
251 }
252
253 free(impl);
254}
255
256const char* icalfileset_path(icalfileset* cluster)
257{
258 struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
259 icalerror_check_arg_rz((cluster!=0),"cluster");
260
261 return impl->path;
262}
263
264
265int icalfileset_lock(icalfileset *cluster)
266{
267#ifndef _WIN32
268 struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
269 struct flock lock;
270 int rtrn;
271
272 icalerror_check_arg_rz((impl->fd>0),"impl->fd");
273 errno = 0;
274 lock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */
275 lock.l_start = 0; /* byte offset relative to l_whence */
276 lock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */
277 lock.l_len = 0; /* #bytes (0 means to EOF) */
278
279 rtrn = fcntl(impl->fd, F_SETLKW, &lock);
280
281 return rtrn;
282#else
283 return -1;
284#endif
285}
286
287int icalfileset_unlock(icalfileset *cluster)
288{
289#ifndef _WIN32
290 struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
291 struct flock lock;
292 icalerror_check_arg_rz((impl->fd>0),"impl->fd");
293
294 lock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */
295 lock.l_start = 0; /* byte offset relative to l_whence */
296 lock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */
297 lock.l_len = 0; /* #bytes (0 means to EOF) */
298
299 return (fcntl(impl->fd, F_UNLCK, &lock));
300#else
301 return -1;
302#endif
303}
304
305#ifdef ICAL_SAFESAVES
306int icalfileset_safe_saves=1;
307#else
308int icalfileset_safe_saves=0;
309#endif
310
311icalerrorenum icalfileset_commit(icalfileset* cluster)
312{
313 char tmp[ICAL_PATH_MAX];
314 char *str;
315 icalcomponent *c;
316 off_t write_size=0;
317
318 struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
319
320 icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR);
321
322 icalerror_check_arg_re((impl->fd>0),"impl->fd is invalid",
323 ICAL_INTERNAL_ERROR) ;
324
325 if (impl->changed == 0 ){
326 return ICAL_NO_ERROR;
327 }
328
329 if(icalfileset_safe_saves == 1){
330 snprintf(tmp,ICAL_PATH_MAX,"cp %s %s.bak",impl->path,impl->path);
331
332 if(system(tmp) < 0){
333 icalerror_set_errno(ICAL_FILE_ERROR);
334 return ICAL_FILE_ERROR;
335 }
336 }
337
338 if(lseek(impl->fd,SEEK_SET,0) < 0){
339 icalerror_set_errno(ICAL_FILE_ERROR);
340 return ICAL_FILE_ERROR;
341 }
342
343 for(c = icalcomponent_get_first_component(impl->cluster,ICAL_ANY_COMPONENT);
344 c != 0;
345 c = icalcomponent_get_next_component(impl->cluster,ICAL_ANY_COMPONENT)){
346 int sz;
347
348 str = icalcomponent_as_ical_string(c);
349
350 sz=write(impl->fd,str,strlen(str));
351
352 if ( sz != strlen(str)){
353 perror("write");
354 icalerror_set_errno(ICAL_FILE_ERROR);
355 return ICAL_FILE_ERROR;
356 }
357
358 write_size += sz;
359 }
360
361 impl->changed = 0;
362
363#ifndef _QTWIN_
364 if(ftruncate(impl->fd,write_size) < 0){
365 return ICAL_FILE_ERROR;
366 }
367#endif
368
369 return ICAL_NO_ERROR;
370
371}
372
373void icalfileset_mark(icalfileset* cluster){
374
375 struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
376
377 icalerror_check_arg_rv((impl!=0),"cluster");
378
379 impl->changed = 1;
380
381}
382
383icalcomponent* icalfileset_get_component(icalfileset* cluster){
384 struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
385
386 icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR);
387
388 return impl->cluster;
389}
390
391
392/* manipulate the components in the cluster */
393
394icalerrorenum icalfileset_add_component(icalfileset *cluster,
395 icalcomponent* child)
396{
397 struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
398
399 icalerror_check_arg_re((cluster!=0),"cluster", ICAL_BADARG_ERROR);
400 icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR);
401
402 icalcomponent_add_component(impl->cluster,child);
403
404 icalfileset_mark(cluster);
405
406 return ICAL_NO_ERROR;
407
408}
409
410icalerrorenum icalfileset_remove_component(icalfileset *cluster,
411 icalcomponent* child)
412{
413 struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
414
415 icalerror_check_arg_re((cluster!=0),"cluster",ICAL_BADARG_ERROR);
416 icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR);
417
418 icalcomponent_remove_component(impl->cluster,child);
419
420 icalfileset_mark(cluster);
421
422 return ICAL_NO_ERROR;
423}
424
425int icalfileset_count_components(icalfileset *cluster,
426 icalcomponent_kind kind)
427{
428 struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
429
430 if(cluster == 0){
431 icalerror_set_errno(ICAL_BADARG_ERROR);
432 return -1;
433 }
434
435 return icalcomponent_count_components(impl->cluster,kind);
436}
437
438icalerrorenum icalfileset_select(icalfileset* set, icalgauge* gauge)
439{
440 struct icalfileset_impl* impl = (struct icalfileset_impl*)set;
441
442 icalerror_check_arg_re(gauge!=0,"guage",ICAL_BADARG_ERROR);
443
444 impl->gauge = gauge;
445
446 return ICAL_NO_ERROR;
447}
448
449void icalfileset_clear(icalfileset* gauge)
450{
451 struct icalfileset_impl* impl = (struct icalfileset_impl*)gauge;
452
453 impl->gauge = 0;
454
455}
456
457icalcomponent* icalfileset_fetch(icalfileset* store,const char* uid)
458{
459 icalcompiter i;
460 struct icalfileset_impl* impl = (struct icalfileset_impl*)store;
461
462 for(i = icalcomponent_begin_component(impl->cluster,ICAL_ANY_COMPONENT);
463 icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){
464
465 icalcomponent *this = icalcompiter_deref(&i);
466 icalcomponent *inner = icalcomponent_get_first_real_component(this);
467 icalcomponent *p;
468 const char *this_uid;
469
470 if(inner != 0){
471 p = icalcomponent_get_first_property(inner,ICAL_UID_PROPERTY);
472 this_uid = icalproperty_get_uid(p);
473
474 if(this_uid==0){
475 icalerror_warn("icalfileset_fetch found a component with no UID");
476 continue;
477 }
478
479 if (strcmp(uid,this_uid)==0){
480 return this;
481 }
482 }
483 }
484
485 return 0;
486}
487
488int icalfileset_has_uid(icalfileset* store,const char* uid)
489{
490 assert(0); /* HACK, not implemented */
491 return 0;
492}
493
494/******* support routines for icalfileset_fetch_match *********/
495
496struct icalfileset_id{
497 char* uid;
498 char* recurrence_id;
499 int sequence;
500};
501
502void icalfileset_id_free(struct icalfileset_id *id)
503{
504 if(id->recurrence_id != 0){
505 free(id->recurrence_id);
506 }
507
508 if(id->uid != 0){
509 free(id->uid);
510 }
511
512}
513
514struct icalfileset_id icalfileset_get_id(icalcomponent* comp)
515{
516
517 icalcomponent *inner;
518 struct icalfileset_id id;
519 icalproperty *p;
520
521 inner = icalcomponent_get_first_real_component(comp);
522
523 p = icalcomponent_get_first_property(inner, ICAL_UID_PROPERTY);
524
525 assert(p!= 0);
526
527 id.uid = strdup(icalproperty_get_uid(p));
528
529 p = icalcomponent_get_first_property(inner, ICAL_SEQUENCE_PROPERTY);
530
531 if(p == 0) {
532 id.sequence = 0;
533 } else {
534 id.sequence = icalproperty_get_sequence(p);
535 }
536
537 p = icalcomponent_get_first_property(inner, ICAL_RECURRENCEID_PROPERTY);
538
539 if (p == 0){
540 id.recurrence_id = 0;
541 } else {
542 icalvalue *v;
543 v = icalproperty_get_value(p);
544 id.recurrence_id = strdup(icalvalue_as_ical_string(v));
545
546 assert(id.recurrence_id != 0);
547 }
548
549 return id;
550}
551
552/* Find the component that is related to the given
553 component. Currently, it just matches based on UID and
554 RECURRENCE-ID */
555icalcomponent* icalfileset_fetch_match(icalfileset* set, icalcomponent *comp)
556{
557 struct icalfileset_impl* impl = (struct icalfileset_impl*)set;
558 icalcompiter i;
559
560 struct icalfileset_id comp_id, match_id;
561
562 comp_id = icalfileset_get_id(comp);
563
564 for(i = icalcomponent_begin_component(impl->cluster,ICAL_ANY_COMPONENT);
565 icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){
566
567 icalcomponent *match = icalcompiter_deref(&i);
568
569 match_id = icalfileset_get_id(match);
570
571 if(strcmp(comp_id.uid, match_id.uid) == 0 &&
572 ( comp_id.recurrence_id ==0 ||
573 strcmp(comp_id.recurrence_id, match_id.recurrence_id) ==0 )){
574
575 /* HACK. What to do with SEQUENCE? */
576
577 icalfileset_id_free(&match_id);
578 icalfileset_id_free(&comp_id);
579 return match;
580
581 }
582
583 icalfileset_id_free(&match_id);
584 }
585
586 icalfileset_id_free(&comp_id);
587 return 0;
588
589}
590
591
592icalerrorenum icalfileset_modify(icalfileset* store, icalcomponent *old,
593 icalcomponent *new)
594{
595 assert(0); /* HACK, not implemented */
596 return ICAL_NO_ERROR;
597}
598
599
600/* Iterate through components */
601icalcomponent* icalfileset_get_current_component (icalfileset* cluster)
602{
603 struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
604
605 icalerror_check_arg_rz((cluster!=0),"cluster");
606
607 return icalcomponent_get_current_component(impl->cluster);
608}
609
610
611icalcomponent* icalfileset_get_first_component(icalfileset* cluster)
612{
613 struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
614 icalcomponent *c=0;
615
616 icalerror_check_arg_rz((cluster!=0),"cluster");
617
618 do {
619 if (c == 0){
620 c = icalcomponent_get_first_component(impl->cluster,
621 ICAL_ANY_COMPONENT);
622 } else {
623 c = icalcomponent_get_next_component(impl->cluster,
624 ICAL_ANY_COMPONENT);
625 }
626
627 if(c != 0 && (impl->gauge == 0 ||
628 icalgauge_compare(impl->gauge,c) == 1)){
629 return c;
630 }
631
632 } while(c != 0);
633
634
635 return 0;
636}
637
638icalcomponent* icalfileset_get_next_component(icalfileset* cluster)
639{
640 struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
641 icalcomponent *c;
642
643 icalerror_check_arg_rz((cluster!=0),"cluster");
644
645 do {
646 c = icalcomponent_get_next_component(impl->cluster,
647 ICAL_ANY_COMPONENT);
648
649 if(c != 0 && (impl->gauge == 0 ||
650 icalgauge_compare(impl->gauge,c) == 1)){
651 return c;
652 }
653
654 } while(c != 0);
655
656
657 return 0;
658}
659