summaryrefslogtreecommitdiffabout
path: root/libical/src/libicalss/icalfileset.c
Side-by-side diff
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 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalfileset.c
+ CREATOR: eric 23 December 1999
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+
+ ======================================================================*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <fcntl.h> /* For open() flags and mode */
+#include <sys/types.h> /* For open() flags and mode */
+#include <sys/stat.h> /* For open() flags and mode */
+
+#include "icalfileset.h"
+#include "icalfilesetimpl.h"
+
+// Eugen C. <eug@thekompany.com>
+#include <defines.h>
+//
+
+int snprintf(char *str, size_t n, char const *fmt, ...);
+
+//extern int errno;
+
+int icalfileset_lock(icalfileset *cluster);
+int icalfileset_unlock(icalfileset *cluster);
+icalerrorenum icalfileset_read_file(icalfileset* cluster, mode_t mode);
+int icalfileset_filesize(icalfileset* cluster);
+
+icalerrorenum icalfileset_create_cluster(const char *path);
+
+icalfileset* icalfileset_new_impl()
+{
+ struct icalfileset_impl* impl;
+
+ if ( ( impl = (struct icalfileset_impl*)
+ malloc(sizeof(struct icalfileset_impl))) == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ errno = ENOMEM;
+ return 0;
+ }
+
+ memset(impl,0,sizeof(struct icalfileset_impl));
+
+ strcpy(impl->id,ICALFILESET_ID);
+
+ return impl;
+}
+
+
+icalfileset* icalfileset_new(const char* path)
+{
+ return icalfileset_new_open(path, O_RDWR|O_CREAT, 0664);
+}
+
+icalfileset* icalfileset_new_open(const char* path, int flags, mode_t mode)
+{
+ struct icalfileset_impl *impl = icalfileset_new_impl();
+ struct icaltimetype tt;
+ off_t cluster_file_size;
+
+ memset(&tt,0,sizeof(struct icaltimetype));
+
+ icalerror_clear_errno();
+ icalerror_check_arg_rz( (path!=0), "path");
+
+ if (impl == 0){
+ return 0;
+ }
+
+ impl->path = strdup(path);
+
+ cluster_file_size = icalfileset_filesize(impl);
+
+ if(cluster_file_size < 0){
+ icalfileset_free(impl);
+ return 0;
+ }
+
+ impl->fd = open(impl->path,flags, mode);
+
+ if (impl->fd < 0){
+ icalerror_set_errno(ICAL_FILE_ERROR);
+ icalfileset_free(impl);
+ return 0;
+ }
+
+ icalfileset_lock(impl);
+
+ if(cluster_file_size > 0 ){
+ icalerrorenum error;
+ if((error = icalfileset_read_file(impl,mode))!= ICAL_NO_ERROR){
+ icalfileset_free(impl);
+ return 0;
+ }
+ }
+
+ if(impl->cluster == 0){
+ impl->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT);
+ }
+
+ return impl;
+}
+
+char* icalfileset_read_from_file(char *s, size_t size, void *d)
+{
+
+ char* p = s;
+ int fd = (int)d;
+
+ /* Simulate fgets -- read single characters and stop at '\n' */
+
+ for(p=s; p<s+size-1;p++){
+
+ if(read(fd,p,1) != 1 || *p=='\n'){
+ p++;
+ break;
+ }
+ }
+
+ *p = '\0';
+
+ if(*s == 0){
+ return 0;
+ } else {
+ return s;
+ }
+
+}
+
+
+icalerrorenum icalfileset_read_file(icalfileset* cluster,mode_t mode)
+{
+
+ icalparser *parser;
+
+ struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
+
+ parser = icalparser_new();
+ icalparser_set_gen_data(parser,(void*)impl->fd);
+ impl->cluster = icalparser_parse(parser,icalfileset_read_from_file);
+ icalparser_free(parser);
+
+ if (impl->cluster == 0 || icalerrno != ICAL_NO_ERROR){
+ icalerror_set_errno(ICAL_PARSE_ERROR);
+ return ICAL_PARSE_ERROR;
+ }
+
+ if (icalcomponent_isa(impl->cluster) != ICAL_XROOT_COMPONENT){
+ /* The parser got a single component, so it did not put it in
+ an XROOT. */
+ icalcomponent *cl = impl->cluster;
+ impl->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT);
+ icalcomponent_add_component(impl->cluster,cl);
+ }
+
+ return ICAL_NO_ERROR;
+
+}
+
+int icalfileset_filesize(icalfileset* cluster)
+{
+ struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
+ int cluster_file_size;
+ struct stat sbuf;
+
+ if (stat(impl->path,&sbuf) != 0){
+
+ /* A file by the given name does not exist, or there was
+ another error */
+ cluster_file_size = 0;
+ if (errno == ENOENT) {
+ /* It was because the file does not exist */
+ return 0;
+ } else {
+ /* It was because of another error */
+ icalerror_set_errno(ICAL_FILE_ERROR);
+ return -1;
+ }
+ } else {
+ /* A file by the given name exists, but is it a regular file? */
+
+#ifndef _QTWIN_
+ if (!S_ISREG(sbuf.st_mode)){
+ /* Nope, not a regular file */
+ icalerror_set_errno(ICAL_FILE_ERROR);
+ return -1;
+ } else {
+ /* Lets assume that it is a file of the right type */
+ return sbuf.st_size;
+ }
+#else
+ return sbuf.st_size;
+#endif
+
+ }
+
+ /*return -1; not reached*/
+}
+
+void icalfileset_free(icalfileset* cluster)
+{
+ struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
+
+ icalerror_check_arg_rv((cluster!=0),"cluster");
+
+ if (impl->cluster != 0){
+ icalfileset_commit(cluster);
+ icalcomponent_free(impl->cluster);
+ impl->cluster=0;
+ }
+
+ if(impl->fd > 0){
+ icalfileset_unlock(impl);
+ close(impl->fd);
+ impl->fd = -1;
+ }
+
+ if(impl->path != 0){
+ free(impl->path);
+ impl->path = 0;
+ }
+
+ free(impl);
+}
+
+const char* icalfileset_path(icalfileset* cluster)
+{
+ struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
+ icalerror_check_arg_rz((cluster!=0),"cluster");
+
+ return impl->path;
+}
+
+
+int icalfileset_lock(icalfileset *cluster)
+{
+#ifndef _WIN32
+ struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
+ struct flock lock;
+ int rtrn;
+
+ icalerror_check_arg_rz((impl->fd>0),"impl->fd");
+ errno = 0;
+ lock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */
+ lock.l_start = 0; /* byte offset relative to l_whence */
+ lock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */
+ lock.l_len = 0; /* #bytes (0 means to EOF) */
+
+ rtrn = fcntl(impl->fd, F_SETLKW, &lock);
+
+ return rtrn;
+#else
+ return -1;
+#endif
+}
+
+int icalfileset_unlock(icalfileset *cluster)
+{
+#ifndef _WIN32
+ struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
+ struct flock lock;
+ icalerror_check_arg_rz((impl->fd>0),"impl->fd");
+
+ lock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */
+ lock.l_start = 0; /* byte offset relative to l_whence */
+ lock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */
+ lock.l_len = 0; /* #bytes (0 means to EOF) */
+
+ return (fcntl(impl->fd, F_UNLCK, &lock));
+#else
+ return -1;
+#endif
+}
+
+#ifdef ICAL_SAFESAVES
+int icalfileset_safe_saves=1;
+#else
+int icalfileset_safe_saves=0;
+#endif
+
+icalerrorenum icalfileset_commit(icalfileset* cluster)
+{
+ char tmp[ICAL_PATH_MAX];
+ char *str;
+ icalcomponent *c;
+ off_t write_size=0;
+
+ struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
+
+ icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR);
+
+ icalerror_check_arg_re((impl->fd>0),"impl->fd is invalid",
+ ICAL_INTERNAL_ERROR) ;
+
+ if (impl->changed == 0 ){
+ return ICAL_NO_ERROR;
+ }
+
+ if(icalfileset_safe_saves == 1){
+ snprintf(tmp,ICAL_PATH_MAX,"cp %s %s.bak",impl->path,impl->path);
+
+ if(system(tmp) < 0){
+ icalerror_set_errno(ICAL_FILE_ERROR);
+ return ICAL_FILE_ERROR;
+ }
+ }
+
+ if(lseek(impl->fd,SEEK_SET,0) < 0){
+ icalerror_set_errno(ICAL_FILE_ERROR);
+ return ICAL_FILE_ERROR;
+ }
+
+ for(c = icalcomponent_get_first_component(impl->cluster,ICAL_ANY_COMPONENT);
+ c != 0;
+ c = icalcomponent_get_next_component(impl->cluster,ICAL_ANY_COMPONENT)){
+ int sz;
+
+ str = icalcomponent_as_ical_string(c);
+
+ sz=write(impl->fd,str,strlen(str));
+
+ if ( sz != strlen(str)){
+ perror("write");
+ icalerror_set_errno(ICAL_FILE_ERROR);
+ return ICAL_FILE_ERROR;
+ }
+
+ write_size += sz;
+ }
+
+ impl->changed = 0;
+
+#ifndef _QTWIN_
+ if(ftruncate(impl->fd,write_size) < 0){
+ return ICAL_FILE_ERROR;
+ }
+#endif
+
+ return ICAL_NO_ERROR;
+
+}
+
+void icalfileset_mark(icalfileset* cluster){
+
+ struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
+
+ icalerror_check_arg_rv((impl!=0),"cluster");
+
+ impl->changed = 1;
+
+}
+
+icalcomponent* icalfileset_get_component(icalfileset* cluster){
+ struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
+
+ icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR);
+
+ return impl->cluster;
+}
+
+
+/* manipulate the components in the cluster */
+
+icalerrorenum icalfileset_add_component(icalfileset *cluster,
+ icalcomponent* child)
+{
+ struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
+
+ icalerror_check_arg_re((cluster!=0),"cluster", ICAL_BADARG_ERROR);
+ icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR);
+
+ icalcomponent_add_component(impl->cluster,child);
+
+ icalfileset_mark(cluster);
+
+ return ICAL_NO_ERROR;
+
+}
+
+icalerrorenum icalfileset_remove_component(icalfileset *cluster,
+ icalcomponent* child)
+{
+ struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
+
+ icalerror_check_arg_re((cluster!=0),"cluster",ICAL_BADARG_ERROR);
+ icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR);
+
+ icalcomponent_remove_component(impl->cluster,child);
+
+ icalfileset_mark(cluster);
+
+ return ICAL_NO_ERROR;
+}
+
+int icalfileset_count_components(icalfileset *cluster,
+ icalcomponent_kind kind)
+{
+ struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
+
+ if(cluster == 0){
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return -1;
+ }
+
+ return icalcomponent_count_components(impl->cluster,kind);
+}
+
+icalerrorenum icalfileset_select(icalfileset* set, icalgauge* gauge)
+{
+ struct icalfileset_impl* impl = (struct icalfileset_impl*)set;
+
+ icalerror_check_arg_re(gauge!=0,"guage",ICAL_BADARG_ERROR);
+
+ impl->gauge = gauge;
+
+ return ICAL_NO_ERROR;
+}
+
+void icalfileset_clear(icalfileset* gauge)
+{
+ struct icalfileset_impl* impl = (struct icalfileset_impl*)gauge;
+
+ impl->gauge = 0;
+
+}
+
+icalcomponent* icalfileset_fetch(icalfileset* store,const char* uid)
+{
+ icalcompiter i;
+ struct icalfileset_impl* impl = (struct icalfileset_impl*)store;
+
+ for(i = icalcomponent_begin_component(impl->cluster,ICAL_ANY_COMPONENT);
+ icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){
+
+ icalcomponent *this = icalcompiter_deref(&i);
+ icalcomponent *inner = icalcomponent_get_first_real_component(this);
+ icalcomponent *p;
+ const char *this_uid;
+
+ if(inner != 0){
+ p = icalcomponent_get_first_property(inner,ICAL_UID_PROPERTY);
+ this_uid = icalproperty_get_uid(p);
+
+ if(this_uid==0){
+ icalerror_warn("icalfileset_fetch found a component with no UID");
+ continue;
+ }
+
+ if (strcmp(uid,this_uid)==0){
+ return this;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int icalfileset_has_uid(icalfileset* store,const char* uid)
+{
+ assert(0); /* HACK, not implemented */
+ return 0;
+}
+
+/******* support routines for icalfileset_fetch_match *********/
+
+struct icalfileset_id{
+ char* uid;
+ char* recurrence_id;
+ int sequence;
+};
+
+void icalfileset_id_free(struct icalfileset_id *id)
+{
+ if(id->recurrence_id != 0){
+ free(id->recurrence_id);
+ }
+
+ if(id->uid != 0){
+ free(id->uid);
+ }
+
+}
+
+struct icalfileset_id icalfileset_get_id(icalcomponent* comp)
+{
+
+ icalcomponent *inner;
+ struct icalfileset_id id;
+ icalproperty *p;
+
+ inner = icalcomponent_get_first_real_component(comp);
+
+ p = icalcomponent_get_first_property(inner, ICAL_UID_PROPERTY);
+
+ assert(p!= 0);
+
+ id.uid = strdup(icalproperty_get_uid(p));
+
+ p = icalcomponent_get_first_property(inner, ICAL_SEQUENCE_PROPERTY);
+
+ if(p == 0) {
+ id.sequence = 0;
+ } else {
+ id.sequence = icalproperty_get_sequence(p);
+ }
+
+ p = icalcomponent_get_first_property(inner, ICAL_RECURRENCEID_PROPERTY);
+
+ if (p == 0){
+ id.recurrence_id = 0;
+ } else {
+ icalvalue *v;
+ v = icalproperty_get_value(p);
+ id.recurrence_id = strdup(icalvalue_as_ical_string(v));
+
+ assert(id.recurrence_id != 0);
+ }
+
+ return id;
+}
+
+/* Find the component that is related to the given
+ component. Currently, it just matches based on UID and
+ RECURRENCE-ID */
+icalcomponent* icalfileset_fetch_match(icalfileset* set, icalcomponent *comp)
+{
+ struct icalfileset_impl* impl = (struct icalfileset_impl*)set;
+ icalcompiter i;
+
+ struct icalfileset_id comp_id, match_id;
+
+ comp_id = icalfileset_get_id(comp);
+
+ for(i = icalcomponent_begin_component(impl->cluster,ICAL_ANY_COMPONENT);
+ icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){
+
+ icalcomponent *match = icalcompiter_deref(&i);
+
+ match_id = icalfileset_get_id(match);
+
+ if(strcmp(comp_id.uid, match_id.uid) == 0 &&
+ ( comp_id.recurrence_id ==0 ||
+ strcmp(comp_id.recurrence_id, match_id.recurrence_id) ==0 )){
+
+ /* HACK. What to do with SEQUENCE? */
+
+ icalfileset_id_free(&match_id);
+ icalfileset_id_free(&comp_id);
+ return match;
+
+ }
+
+ icalfileset_id_free(&match_id);
+ }
+
+ icalfileset_id_free(&comp_id);
+ return 0;
+
+}
+
+
+icalerrorenum icalfileset_modify(icalfileset* store, icalcomponent *old,
+ icalcomponent *new)
+{
+ assert(0); /* HACK, not implemented */
+ return ICAL_NO_ERROR;
+}
+
+
+/* Iterate through components */
+icalcomponent* icalfileset_get_current_component (icalfileset* cluster)
+{
+ struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
+
+ icalerror_check_arg_rz((cluster!=0),"cluster");
+
+ return icalcomponent_get_current_component(impl->cluster);
+}
+
+
+icalcomponent* icalfileset_get_first_component(icalfileset* cluster)
+{
+ struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
+ icalcomponent *c=0;
+
+ icalerror_check_arg_rz((cluster!=0),"cluster");
+
+ do {
+ if (c == 0){
+ c = icalcomponent_get_first_component(impl->cluster,
+ ICAL_ANY_COMPONENT);
+ } else {
+ c = icalcomponent_get_next_component(impl->cluster,
+ ICAL_ANY_COMPONENT);
+ }
+
+ if(c != 0 && (impl->gauge == 0 ||
+ icalgauge_compare(impl->gauge,c) == 1)){
+ return c;
+ }
+
+ } while(c != 0);
+
+
+ return 0;
+}
+
+icalcomponent* icalfileset_get_next_component(icalfileset* cluster)
+{
+ struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
+ icalcomponent *c;
+
+ icalerror_check_arg_rz((cluster!=0),"cluster");
+
+ do {
+ c = icalcomponent_get_next_component(impl->cluster,
+ ICAL_ANY_COMPONENT);
+
+ if(c != 0 && (impl->gauge == 0 ||
+ icalgauge_compare(impl->gauge,c) == 1)){
+ return c;
+ }
+
+ } while(c != 0);
+
+
+ return 0;
+}
+