diff options
Diffstat (limited to 'camel/providers/local')
-rw-r--r-- | camel/providers/local/camel-local-provider.c | 2 | ||||
-rw-r--r-- | camel/providers/local/camel-local-store.c | 133 | ||||
-rw-r--r-- | camel/providers/local/camel-local-summary.c | 2 | ||||
-rw-r--r-- | camel/providers/local/camel-maildir-folder.c | 6 | ||||
-rw-r--r-- | camel/providers/local/camel-maildir-store.c | 66 | ||||
-rw-r--r-- | camel/providers/local/camel-maildir-summary.c | 5 | ||||
-rw-r--r-- | camel/providers/local/camel-mbox-store.c | 12 | ||||
-rw-r--r-- | camel/providers/local/camel-mh-folder.c | 4 | ||||
-rw-r--r-- | camel/providers/local/camel-mh-store.c | 12 |
9 files changed, 191 insertions, 51 deletions
diff --git a/camel/providers/local/camel-local-provider.c b/camel/providers/local/camel-local-provider.c index 603a4a7bf9..ccf7aa58df 100644 --- a/camel/providers/local/camel-local-provider.c +++ b/camel/providers/local/camel-local-provider.c @@ -66,8 +66,6 @@ static CamelProvider maildir_provider = { void camel_provider_module_init(CamelSession * session) { - printf("Initialising local providers\n"); - mh_provider.object_types[CAMEL_PROVIDER_STORE] = camel_mh_store_get_type(); mh_provider.service_cache = g_hash_table_new(camel_url_hash, camel_url_equal); camel_session_register_provider(session, &mh_provider); diff --git a/camel/providers/local/camel-local-store.c b/camel/providers/local/camel-local-store.c index c07a1d2c3a..748cc45290 100644 --- a/camel/providers/local/camel-local-store.c +++ b/camel/providers/local/camel-local-store.c @@ -33,11 +33,16 @@ #include "camel-exception.h" #include "camel-url.h" +#define d(x) + /* Returns the class for a CamelLocalStore */ #define CLOCALS_CLASS(so) CAMEL_LOCAL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) #define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) +static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); static char *get_name(CamelService *service, gboolean brief); +static char *get_root_folder_name (CamelStore *store, CamelException *ex); +static char *get_default_folder_name (CamelStore *store, CamelException *ex); static void rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex); static char *get_folder_name(CamelStore *store, const char *folder_name, CamelException *ex); static CamelFolderInfo *get_folder_info (CamelStore *store, const char *top, @@ -55,6 +60,9 @@ camel_local_store_class_init (CamelLocalStoreClass *camel_local_store_class) /* virtual method overload */ camel_service_class->get_name = get_name; + camel_store_class->get_folder = get_folder; + camel_store_class->get_root_folder_name = get_root_folder_name; + camel_store_class->get_default_folder_name = get_default_folder_name; camel_store_class->get_folder_name = get_folder_name; camel_store_class->get_folder_info = get_folder_info; camel_store_class->free_folder_info = camel_store_free_folder_info_full; @@ -99,6 +107,73 @@ camel_local_store_get_toplevel_dir (CamelLocalStore *store) return url->path; } +static CamelFolder * +get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex) +{ + struct stat st; + char *path = ((CamelService *)store)->url->path; + char *sub, *slash; + + if (path[0] != '/') { + camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, + _("Store root %s is not an absolute path"), path); + return NULL; + } + + if (stat(path, &st) == 0) { + if (!S_ISDIR(st.st_mode)) { + camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, + _("Store root %s is not a regular directory"), path); + } + return NULL; + } + + if (errno != ENOENT + || (flags & CAMEL_STORE_FOLDER_CREATE) == 0) { + camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, + _("Cannot get folder: %s: %s"), path, strerror(errno)); + return NULL; + } + + /* need to create the dir heirarchy */ + sub = alloca(strlen(path)+1); + strcpy(sub, path); + slash = sub; + do { + slash = strchr(slash+1, '/'); + if (slash) + *slash = 0; + if (stat(sub, &st) == -1) { + if (errno != ENOENT + || mkdir(sub, 0700) == -1) { + camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, + _("Cannot get folder: %s: %s"), path, strerror(errno)); + return NULL; + } + } + if (slash) + *slash = '/'; + } while (slash); + + return NULL; +} + +static char * +get_root_folder_name(CamelStore *store, CamelException *ex) +{ + camel_exception_set(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, + _("Local stores do not have a root folder")); + return NULL; +} + +static char * +get_default_folder_name(CamelStore *store, CamelException *ex) +{ + camel_exception_set(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, + _("Local stores do not have a default folder")); + return NULL; +} + static char * get_folder_name (CamelStore *store, const char *folder_name, CamelException *ex) { @@ -134,25 +209,49 @@ get_folder_info (CamelStore *store, const char *top, return NULL; } -static int xrename(const char *oldp, const char *newp, const char *prefix, const char *suffix, CamelException *ex) +static int xrename(const char *oldp, const char *newp, const char *prefix, const char *suffix, int missingok, CamelException *ex) { struct stat st; char *old = g_strconcat(prefix, oldp, suffix, 0); char *new = g_strconcat(prefix, newp, suffix, 0); int ret = -1; + int err = 0; + + d(printf("renaming %s%s to %s%s\n", oldp, suffix, newp, suffix)); - printf("renaming %s%s to %s%s\n", oldp, suffix, newp, suffix); + if (stat(old, &st) == -1) { + if (missingok && errno == ENOENT) { + ret = 0; + } else { + err = errno; + ret = -1; + } + } else if (S_ISDIR(st.st_mode)) { /* use rename for dirs */ + if (rename(old, new) == 0 + || stat(new, &st) == 0) { + ret = 0; + } else { + err = errno; + ret = -1; + } + } else if (link(old, new) == 0 /* and link for files */ + || (stat(new, &st) == 0 && st.st_nlink == 2)) { + if (unlink(old) == 0) { + ret = 0; + } else { + err = errno; + unlink(new); + ret = -1; + } + } else { + err = errno; + ret = -1; + } - /* FIXME: this has races ... */ - if (!(stat(new, &st) == -1 && errno==ENOENT)) { + if (ret == -1) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not rename folder %s to %s: destination exists"), - old, new); - } else if (rename(old, new) == 0 || errno==ENOENT) { - ret = 0; - } else if (stat(old, &st) == -1 && errno==ENOENT && stat(new, &st) == 0) { - /* for nfs, check if the rename worked anyway ... */ - ret = 0; + _("Could not rename folder %s to %s: %s"), + old, new, strerror(err)); } g_free(old); @@ -167,16 +266,16 @@ rename_folder(CamelStore *store, const char *old, const char *new, CamelExceptio char *path = CAMEL_SERVICE (store)->url->path; /* try to rollback failures, has obvious races */ - if (xrename(old, new, path, ".ibex", ex)) { + if (xrename(old, new, path, ".ibex", TRUE, ex)) { return; } - if (xrename(old, new, path, ".ev-summary", ex)) { - xrename(new, old, path, ".ibex", ex); + if (xrename(old, new, path, ".ev-summary", TRUE, ex)) { + xrename(new, old, path, ".ibex", TRUE, ex); return; } - if (xrename(old, new, path, "", ex)) { - xrename(new, old, path, ".ev-summary", ex); - xrename(new, old, path, ".ibex", ex); + if (xrename(old, new, path, "", FALSE, ex)) { + xrename(new, old, path, ".ev-summary", TRUE, ex); + xrename(new, old, path, ".ibex", TRUE, ex); } } diff --git a/camel/providers/local/camel-local-summary.c b/camel/providers/local/camel-local-summary.c index 278df6a64c..81cde8e808 100644 --- a/camel/providers/local/camel-local-summary.c +++ b/camel/providers/local/camel-local-summary.c @@ -168,7 +168,7 @@ camel_local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->decode_x_evolution(cls, xev, info); } -#define DOSTATS +/*#define DOSTATS*/ #ifdef DOSTATS struct _stat_info { int mitotal; diff --git a/camel/providers/local/camel-maildir-folder.c b/camel/providers/local/camel-maildir-folder.c index e3ff088238..1cffbdabd2 100644 --- a/camel/providers/local/camel-maildir-folder.c +++ b/camel/providers/local/camel-maildir-folder.c @@ -40,9 +40,9 @@ #include "camel-mime-message.h" #include "camel-exception.h" -#define d(x) (printf("%s(%d): ", __FILE__, __LINE__),(x)) +#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ -static CamelFolderClass *parent_class = NULL; +static CamelLocalFolderClass *parent_class = NULL; /* Returns the class for a CamelMaildirFolder */ #define CMAILDIRF_CLASS(so) CAMEL_MAILDIR_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) @@ -61,7 +61,7 @@ static void camel_maildir_folder_class_init(CamelObjectClass * camel_maildir_fol CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_maildir_folder_class); CamelLocalFolderClass *lclass = (CamelLocalFolderClass *)camel_maildir_folder_class; - parent_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_folder_get_type())); + parent_class = CAMEL_LOCAL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_local_folder_get_type())); /* virtual method definition */ diff --git a/camel/providers/local/camel-maildir-store.c b/camel/providers/local/camel-maildir-store.c index 0601307449..f5bd353b6f 100644 --- a/camel/providers/local/camel-maildir-store.c +++ b/camel/providers/local/camel-maildir-store.c @@ -27,6 +27,8 @@ #include <string.h> #include <unistd.h> +#include <dirent.h> + #include "camel-maildir-store.h" #include "camel-maildir-folder.h" #include "camel-exception.h" @@ -47,7 +49,7 @@ static void camel_maildir_store_class_init(CamelObjectClass * camel_maildir_stor CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_maildir_store_class); /*CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_maildir_store_class);*/ - parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_folder_get_type()); + parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type()); /* virtual method overload, use defaults for most */ camel_store_class->get_folder = get_folder; @@ -85,6 +87,10 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin struct stat st; CamelFolder *folder = NULL; + (void) ((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex); + if (camel_exception_is_set(ex)) + return NULL; + name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name); tmp = g_strdup_printf("%s/tmp", name); cur = g_strdup_printf("%s/cur", name); @@ -99,8 +105,6 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, _("Folder `%s' does not exist."), folder_name); } else { - printf("creating ...\n"); - if (mkdir(name, 0700) != 0 || mkdir(tmp, 0700) != 0 || mkdir(cur, 0700) != 0 @@ -113,7 +117,6 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin rmdir(new); rmdir(name); } else { - printf("created ok?\n"); folder = camel_maildir_folder_new(store, folder_name, flags, ex); } } @@ -138,23 +141,62 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex) { char *name, *tmp, *cur, *new; + struct stat st; name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name); + tmp = g_strdup_printf("%s/tmp", name); cur = g_strdup_printf("%s/cur", name); new = g_strdup_printf("%s/new", name); - /* remove subdirs first - will fail if not empty */ - if ((rmdir(tmp) == -1 && errno != ENOENT) - || (rmdir(new) == -1 && errno != ENOENT) - || (rmdir(cur) == -1 && errno != ENOENT) - || (rmdir(name) == -1 && errno != ENOENT)) { + if (stat(name, &st) == -1 || !S_ISDIR(st.st_mode) + || stat(tmp, &st) == -1 || !S_ISDIR(st.st_mode) + || stat(cur, &st) == -1 || !S_ISDIR(st.st_mode) + || stat(new, &st) == -1 || !S_ISDIR(st.st_mode)) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Could not delete folder `%s': %s"), - folder_name, strerror(errno)); + folder_name, errno?strerror(errno):_("not a maildir directory")); } else { - /* and remove metadata */ - ((CamelStoreClass *)parent_class)->delete_folder(store, folder_name, ex); + int err = 0; + + /* remove subdirs first - will fail if not empty */ + if (rmdir(cur) == -1 || rmdir(new) == -1) { + err = errno; + } else { + DIR *dir; + struct dirent *d; + + /* for tmp (only), its contents is irrelevant */ + dir = opendir(tmp); + if (dir) { + while ( (d=readdir(dir)) ) { + char *name = d->d_name, *file; + + if (!strcmp(name, ".") || !strcmp(name, "..")) + continue; + file = g_strdup_printf("%s/%s", tmp, name); + unlink(file); + g_free(file); + } + closedir(dir); + } + if (rmdir(tmp) == -1 || rmdir(name) == -1) + err = errno; + } + + if (err != 0) { + /* easier just to mkdir all (and let them fail), than remember what we got to */ + mkdir(name, 0700); + mkdir(cur, 0700); + mkdir(new, 0700); + mkdir(tmp, 0700); + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, + _("Could not delete folder `%s': %s"), + folder_name, strerror(err)); + } else { + /* and remove metadata */ + ((CamelStoreClass *)parent_class)->delete_folder(store, folder_name, ex); + } } g_free(name); diff --git a/camel/providers/local/camel-maildir-summary.c b/camel/providers/local/camel-maildir-summary.c index 92b2be23f8..fe88539ca3 100644 --- a/camel/providers/local/camel-maildir-summary.c +++ b/camel/providers/local/camel-maildir-summary.c @@ -33,7 +33,7 @@ #include <ctype.h> -#define d(x) (printf("%s(%d): ", __FILE__, __LINE__),(x)) +#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ #define CAMEL_MAILDIR_SUMMARY_VERSION (0x2000) @@ -103,6 +103,9 @@ camel_maildir_summary_init (CamelMaildirSummary *o) /* set unique file version */ s->version += CAMEL_MAILDIR_SUMMARY_VERSION; + s->message_info_size = sizeof(CamelMaildirMessageInfo); + s->content_info_size = sizeof(CamelMaildirMessageContentInfo); + if (gethostname(hostname, 256) == 0) { o->priv->hostname = g_strdup(hostname); } else { diff --git a/camel/providers/local/camel-mbox-store.c b/camel/providers/local/camel-mbox-store.c index 77a291637c..8ae0891b31 100644 --- a/camel/providers/local/camel-mbox-store.c +++ b/camel/providers/local/camel-mbox-store.c @@ -47,7 +47,7 @@ camel_mbox_store_class_init (CamelMboxStoreClass *camel_mbox_store_class) { CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_mbox_store_class); - parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_folder_get_type()); + parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type()); /* virtual method overload */ camel_store_class->get_folder = get_folder; @@ -87,6 +87,10 @@ get_folder(CamelStore *store, const char *folder_name, guint32 flags, CamelExcep char *name; struct stat st; + (void) ((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex); + if (camel_exception_is_set(ex)) + return NULL; + name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name); if (stat(name, &st) == -1) { @@ -137,12 +141,6 @@ delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) name = g_strdup_printf ("%s%s", CAMEL_SERVICE (store)->url->path, folder_name); if (stat (name, &st) == -1) { - if (errno == ENOENT) { - /* file doesn't exist - it's kinda like deleting it ;-) */ - g_free (name); - return; - } - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Could not delete folder `%s':\n%s"), folder_name, g_strerror (errno)); diff --git a/camel/providers/local/camel-mh-folder.c b/camel/providers/local/camel-mh-folder.c index c0a9f3f2af..8f223a34c2 100644 --- a/camel/providers/local/camel-mh-folder.c +++ b/camel/providers/local/camel-mh-folder.c @@ -42,7 +42,7 @@ #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ -static CamelFolderClass *parent_class = NULL; +static CamelLocalFolderClass *parent_class = NULL; /* Returns the class for a CamelMhFolder */ #define CMHF_CLASS(so) CAMEL_MH_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) @@ -61,7 +61,7 @@ static void camel_mh_folder_class_init(CamelObjectClass * camel_mh_folder_class) CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_mh_folder_class); CamelLocalFolderClass *lclass = (CamelLocalFolderClass *)camel_mh_folder_class; - parent_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_folder_get_type())); + parent_class = CAMEL_LOCAL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_local_folder_get_type())); /* virtual method definition */ diff --git a/camel/providers/local/camel-mh-store.c b/camel/providers/local/camel-mh-store.c index 82310578d1..3d637e4cad 100644 --- a/camel/providers/local/camel-mh-store.c +++ b/camel/providers/local/camel-mh-store.c @@ -47,7 +47,7 @@ static void camel_mh_store_class_init(CamelObjectClass * camel_mh_store_class) CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_mh_store_class); /*CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_mh_store_class);*/ - parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_folder_get_type()); + parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type()); /* virtual method overload, use defaults for most */ camel_store_class->get_folder = get_folder; @@ -84,6 +84,10 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin char *name; struct stat st; + (void) ((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex); + if (camel_exception_is_set(ex)) + return NULL; + name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name); if (stat(name, &st) == -1) { @@ -100,8 +104,6 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin g_free (name); return NULL; } - printf("creating ...\n"); - if (mkdir(name, 0700) != 0) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Could not create folder `%s':\n%s"), @@ -109,8 +111,6 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin g_free (name); return NULL; } - printf("created ok?\n"); - } else if (!S_ISDIR(st.st_mode)) { camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, _("`%s' is not a directory."), name); @@ -128,7 +128,7 @@ static void delete_folder(CamelStore * store, const char *folder_name, CamelExce /* remove folder directory - will fail if not empty */ name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name); - if (rmdir(name) == -1 && errno != ENOENT) { + if (rmdir(name) == -1) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Could not delete folder `%s': %s"), folder_name, strerror(errno)); |