aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/local
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers/local')
-rw-r--r--camel/providers/local/camel-local-provider.c2
-rw-r--r--camel/providers/local/camel-local-store.c133
-rw-r--r--camel/providers/local/camel-local-summary.c2
-rw-r--r--camel/providers/local/camel-maildir-folder.c6
-rw-r--r--camel/providers/local/camel-maildir-store.c66
-rw-r--r--camel/providers/local/camel-maildir-summary.c5
-rw-r--r--camel/providers/local/camel-mbox-store.c12
-rw-r--r--camel/providers/local/camel-mh-folder.c4
-rw-r--r--camel/providers/local/camel-mh-store.c12
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));