diff options
author | Not Zed <NotZed@HelixCode.com> | 2000-11-28 21:13:23 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2000-11-28 21:13:23 +0800 |
commit | 3998a03ae925f47cd1ffcf31fca0a4701f8c75da (patch) | |
tree | 2e4abfb292e1e76da06af4ce5676fd7ae79d2c75 /camel/providers/local/camel-local-store.c | |
parent | f306b8b912a19e1a0321af66a29faf23664f2077 (diff) | |
download | gsoc2013-evolution-3998a03ae925f47cd1ffcf31fca0a4701f8c75da.tar gsoc2013-evolution-3998a03ae925f47cd1ffcf31fca0a4701f8c75da.tar.gz gsoc2013-evolution-3998a03ae925f47cd1ffcf31fca0a4701f8c75da.tar.bz2 gsoc2013-evolution-3998a03ae925f47cd1ffcf31fca0a4701f8c75da.tar.lz gsoc2013-evolution-3998a03ae925f47cd1ffcf31fca0a4701f8c75da.tar.xz gsoc2013-evolution-3998a03ae925f47cd1ffcf31fca0a4701f8c75da.tar.zst gsoc2013-evolution-3998a03ae925f47cd1ffcf31fca0a4701f8c75da.zip |
Set the info size's properly, oops!
2000-11-28 Not Zed <NotZed@HelixCode.com>
* providers/local/camel-maildir-summary.c
(camel_maildir_summary_init): Set the info size's properly, oops!
* tests/lib/folders.[ch]: Folder testing helpers.
* tests/folder/test2.c: Test basic message ops on folders.
* tests/folder/test1.c (main): Test basic folder ops on (local)
stores.
* providers/local/camel-local-provider.c
(camel_provider_module_init): Removed some debug.
* providers/local/camel-maildir-folder.c
(camel_maildir_folder_class_init): fix parent class.
* providers/local/camel-mh-folder.c (camel_mh_folder_class_init):
Fix parent class (damn cut & paste).
* providers/local/camel-maildir-store.c (get_folder): Call parent
impl.
(camel_maildir_store_class_init): Fix parent class setup.
(delete_folder): Check the folder exists before trying to delete
it.
(delete_folder): Try and make the delete operation atomic/rollback
failures. e.g. if one directory isn't empty, then create the
other empty ones back. Also clear the tmp directory fully first.
* providers/local/camel-mbox-store.c (get_folder): Call parent
impl.
(camel_mbox_store_class_init): parent class is camel_local_store,
not camel_folder, oops.
(delete_folder): Return an error if it doesn't exist, rather than
covering it up.
* providers/local/camel-mh-store.c (get_folder): Call parent impl.
(camel_mh_store_class_init): fix parent class setup.
(delete_folder): Error if it doesn't exist now.
* camel-folder.c (camel_folder_move_message_to):
(camel_folder_copy_message_to): Added warnings as these functions
are going to be removed later.
* camel-store.c (camel_store_get_root_folder): Fix for an early
api change. We want CAMEL_STORE_FOLDER_CREATE, not TRUE, since
its a flag.
(camel_store_get_default_folder): And here too.
* providers/local/camel-local-store.c (xrename): Handle renaming
folders differently to renaming files.
(get_default_folder_name): local stores dont have a default
folder, so make it so. Or at least, it doesn't seem to make sense
to have one.
(get_root_folder_name): Same for root.
(get_folder): Added parent implementation, that makes sure the
service path exists, if we are creating a new folder (but doesn't
create the folder).
2000-11-27 Not Zed <NotZed@HelixCode.com>
* providers/local/camel-local-store.c (xrename): Fixed races. Use
link/unlink, rather than rename, to properly detect overwriting
another file. And allow some files to be missing.
* providers/Makefile.am: Removed mh, mbox, added local, to the default.
svn path=/trunk/; revision=6693
Diffstat (limited to 'camel/providers/local/camel-local-store.c')
-rw-r--r-- | camel/providers/local/camel-local-store.c | 133 |
1 files changed, 116 insertions, 17 deletions
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); } } |