From a8bba62fabeed89980af0912ad49a2b7472d19f6 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Tue, 8 Aug 2000 03:42:47 +0000 Subject: [PATCH] Only retry another uid if we had a name clash, otherwise fail. 2000-08-07 Not Zed * providers/mh/camel-mh-folder.c (mh_append_message): Only retry another uid if we had a name clash, otherwise fail. 2000-08-04 Not Zed * camel-url.c (camel_url_set_protocol): (camel_url_set_host): (camel_url_set_path): (camel_url_set_port): Url editing functions. 2000-08-02 Not Zed * providers/mh/camel-mh-summary.c (camel_mh_summary_sync): Expunge from the end, so the index isn't messed up when you remove a message. * providers/mh/camel-mh-folder.c (mh_append_message): Fix a bug where it would never open an output file/uid. * providers/mbox/camel-mbox-store.c (rename_folder): Implementation for mbox as well. * camel-store.c (camel_store_rename_folder): New method to rename folders. (rename_folder): Default implementation. * providers/mh/camel-mh-store.c (delete_folder): Implement this. (rename_folder): Implement a rename operation. --- camel/ChangeLog | 30 ++++++++++++++++++ camel/camel-store.c | 40 ++++++++++++++++++++++++ camel/camel-store.h | 9 +++++- camel/camel-url.c | 22 +++++++++++++ camel/camel-url.h | 9 ++++-- camel/providers/mbox/camel-mbox-store.c | 50 ++++++++++++++++++++++++++++-- camel/providers/mh/camel-mh-folder.c | 3 +- camel/providers/mh/camel-mh-store.c | 55 +++++++++++++++++++++++++++++++-- camel/providers/mh/camel-mh-summary.c | 6 ++-- 9 files changed, 212 insertions(+), 12 deletions(-) diff --git a/camel/ChangeLog b/camel/ChangeLog index 63ee275..ec58af3 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,33 @@ +2000-08-07 Not Zed + + * providers/mh/camel-mh-folder.c (mh_append_message): Only retry + another uid if we had a name clash, otherwise fail. + +2000-08-04 Not Zed + + * camel-url.c (camel_url_set_protocol): + (camel_url_set_host): + (camel_url_set_path): + (camel_url_set_port): Url editing functions. + +2000-08-02 Not Zed + + * providers/mh/camel-mh-summary.c (camel_mh_summary_sync): Expunge + from the end, so the index isn't messed up when you remove a + message. + + * providers/mh/camel-mh-folder.c (mh_append_message): Fix a bug + where it would never open an output file/uid. + + * providers/mbox/camel-mbox-store.c (rename_folder): + Implementation for mbox as well. + + * camel-store.c (camel_store_rename_folder): New method to rename folders. + (rename_folder): Default implementation. + + * providers/mh/camel-mh-store.c (delete_folder): Implement this. + (rename_folder): Implement a rename operation. + 2000-08-07 Jeffrey Stedfast * providers/imap/camel-imap-folder.c diff --git a/camel/camel-store.c b/camel/camel-store.c index d729bf1..3be983e 100644 --- a/camel/camel-store.c +++ b/camel/camel-store.c @@ -38,6 +38,8 @@ static CamelFolder *get_folder (CamelStore *store, const char *folder_name, gboolean create, CamelException *ex); static void delete_folder (CamelStore *store, const char *folder_name, 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); @@ -62,6 +64,7 @@ camel_store_class_init (CamelStoreClass *camel_store_class) /* virtual method definition */ camel_store_class->get_folder = get_folder; camel_store_class->delete_folder = delete_folder; + camel_store_class->rename_folder = rename_folder; camel_store_class->get_folder_name = get_folder_name; camel_store_class->get_root_folder_name = get_root_folder_name; camel_store_class->get_default_folder_name = get_default_folder_name; @@ -138,6 +141,16 @@ delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) gtk_type_name (GTK_OBJECT_TYPE (store))); } +static void rename_folder (CamelStore *store, const char *old_name, + const char *new_name, CamelException *ex) +{ + g_warning ("CamelStore::rename_folder not implemented for `%s'", + gtk_type_name (GTK_OBJECT_TYPE (store))); + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, + "rename folder unimplemented for: %s", + gtk_type_name (GTK_OBJECT_TYPE (store))); +} + /* CamelStore::get_folder_name should: * a) make sure that the provided name is valid @@ -287,6 +300,33 @@ camel_store_delete_folder (CamelStore *store, const char *folder_name, } } +/** + * camel_store_rename_folder: + * @store: + * @old_name: + * @new_name: + * @ex: + * + * Rename a named folder to a new name. + **/ +void camel_store_rename_folder (CamelStore *store, + const char *old_name, + const char *new_name, + CamelException *ex) +{ + char *old, *new; + + old = CS_CLASS (store)->get_folder_name(store, old_name, ex); + if (old) { + new = CS_CLASS (store)->get_folder_name(store, new_name, ex); + if (new) { + CS_CLASS (store)->rename_folder(store, old, new, ex); + g_free(new); + } + g_free(old); + } +} + /** * camel_store_get_root_folder: return the top-level folder diff --git a/camel/camel-store.h b/camel/camel-store.h index 6d2d9e5..3fc029d 100644 --- a/camel/camel-store.h +++ b/camel/camel-store.h @@ -63,7 +63,10 @@ typedef struct { void (*delete_folder) (CamelStore *store, const char *folder_name, CamelException *ex); - + void (*rename_folder) (CamelStore *store, + const char *old_name, + const char *new_name, + CamelException *ex); char * (*get_folder_name) (CamelStore *store, const char *folder_name, CamelException *ex); @@ -99,6 +102,10 @@ CamelFolder * camel_store_get_default_folder (CamelStore *store, void camel_store_delete_folder (CamelStore *store, const char *folder_name, CamelException *ex); +void camel_store_rename_folder (CamelStore *store, + const char *old_name, + const char *new_name, + CamelException *ex); #ifdef __cplusplus } diff --git a/camel/camel-url.c b/camel/camel-url.c index 6038500..e52645c 100644 --- a/camel/camel-url.c +++ b/camel/camel-url.c @@ -233,6 +233,28 @@ camel_url_free (CamelURL *url) g_free (url); } +void camel_url_set_protocol(CamelURL *url, const char *p) +{ + g_free(url->protocol); + url->protocol = g_strdup(p); +} + +void camel_url_set_host(CamelURL *url, const char *h) +{ + g_free(url->host); + url->host = g_strdup(h); +} + +void camel_url_set_port(CamelURL *url, int port) +{ + url->port = port; +} +void camel_url_set_path(CamelURL *url, const char *p) +{ + g_free(url->path); + url->path = g_strdup(p); +} + /** * camel_url_encode: diff --git a/camel/camel-url.h b/camel/camel-url.h index bea1c43..aba903c 100644 --- a/camel/camel-url.h +++ b/camel/camel-url.h @@ -53,10 +53,15 @@ CamelURL *camel_url_new (const char *url_string, CamelException *ex); char *camel_url_to_string (CamelURL *url, gboolean show_password); void camel_url_free (CamelURL *url); -char *camel_url_encode (char *part, gboolean escape_unsafe, - char *escape_extra); +char *camel_url_encode (char *part, gboolean escape_unsafe, char *escape_extra); void camel_url_decode (char *part); +/* for editing url's */ +void camel_url_set_protocol(CamelURL *url, const char *); +void camel_url_set_host(CamelURL *url, const char *); +void camel_url_set_port(CamelURL *url, int port); +void camel_url_set_path(CamelURL *url, const char *); + /* for putting url's into hash tables */ guint camel_url_hash (const void *v); int camel_url_equal(const void *v, const void *v2); diff --git a/camel/providers/mbox/camel-mbox-store.c b/camel/providers/mbox/camel-mbox-store.c index 19b7c54..e3396a7 100644 --- a/camel/providers/mbox/camel-mbox-store.c +++ b/camel/providers/mbox/camel-mbox-store.c @@ -44,6 +44,7 @@ static CamelFolder *get_folder (CamelStore *store, const char *folder_name, gboolean create, CamelException *ex); static void delete_folder (CamelStore *store, const char *folder_name, 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); @@ -58,6 +59,7 @@ camel_mbox_store_class_init (CamelMboxStoreClass *camel_mbox_store_class) camel_store_class->get_folder = get_folder; camel_store_class->delete_folder = delete_folder; + camel_store_class->rename_folder = rename_folder; camel_store_class->get_folder_name = get_folder_name; } @@ -169,8 +171,7 @@ delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) struct stat st; int status; - name = g_strdup_printf ("%s%s", CAMEL_SERVICE (store)->url->path, - folder_name); + 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 ;-) */ @@ -220,6 +221,51 @@ delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) } } +static int xrename(char *oldp, char *newp, char *prefix, char *suffix, CamelException *ex) +{ + struct stat st; + char *old = g_strconcat(prefix, oldp, suffix, 0); + char *new = g_strconcat(prefix, newp, suffix, 0); + int ret = -1; + + printf("renaming %s%s to %s%s\n", oldp, suffix, newp, suffix); + + /* FIXME: this has races ... */ + if (!(stat(new, &st) == -1 && errno==ENOENT)) { + 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; + } + printf("success = %d\n", ret); + + g_free(old); + g_free(new); + return ret; +} + +static void rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) +{ + char *path = CAMEL_SERVICE (store)->url->path; + + /* try to rollback failures, has obvious races */ + if (xrename(old, new, path, ".ibex", ex)) { + return; + } + if (xrename(old, new, path, "-ev-summary", ex)) { + xrename(new, old, path, ".ibex", ex); + return; + } + if (xrename(old, new, path, "", ex)) { + xrename(new, old, path, "-ev-summary", ex); + xrename(new, old, path, ".ibex", ex); + } +} + static char * get_folder_name (CamelStore *store, const char *folder_name, CamelException *ex) { diff --git a/camel/providers/mh/camel-mh-folder.c b/camel/providers/mh/camel-mh-folder.c index 1961c62..6f85fb7 100644 --- a/camel/providers/mh/camel-mh-folder.c +++ b/camel/providers/mh/camel-mh-folder.c @@ -268,7 +268,6 @@ static gint mh_get_unread_message_count(CamelFolder * folder) return count; } -/* FIXME: this may need some tweaking for performance? */ static void mh_append_message(CamelFolder * folder, CamelMimeMessage * message, guint32 flags, CamelException * ex) { CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder); @@ -285,7 +284,7 @@ static void mh_append_message(CamelFolder * folder, CamelMimeMessage * message, uid = camel_folder_summary_next_uid_string((CamelFolderSummary *)mh_folder->summary); name = g_strdup_printf("%s/%s", mh_folder->folder_file_path, uid); output_stream = camel_stream_fs_new_with_name(name, O_WRONLY|O_CREAT|O_EXCL, 0600); - } while (output_stream == NULL || errno != EEXIST); + } while (output_stream == NULL && errno == EEXIST); if (output_stream == NULL) goto fail; diff --git a/camel/providers/mh/camel-mh-store.c b/camel/providers/mh/camel-mh-store.c index 6ae885a..5ab4bcc 100644 --- a/camel/providers/mh/camel-mh-store.c +++ b/camel/providers/mh/camel-mh-store.c @@ -43,6 +43,7 @@ static char *get_name(CamelService * service, gboolean brief); static CamelFolder *get_folder(CamelStore * store, const char *folder_name, gboolean create, CamelException * ex); static void delete_folder(CamelStore * store, const char *folder_name, 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 void camel_mh_store_class_init(CamelMhStoreClass * camel_mh_store_class) @@ -55,6 +56,7 @@ static void camel_mh_store_class_init(CamelMhStoreClass * camel_mh_store_class) camel_store_class->get_folder = get_folder; camel_store_class->delete_folder = delete_folder; + camel_store_class->rename_folder = rename_folder; camel_store_class->get_folder_name = get_folder_name; } @@ -107,8 +109,11 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, gboo name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name); + printf("getting folder: %s\n", name); if (stat(name, &st) == -1) { int fd; + + printf("doesn't exist ...\n"); if (errno != ENOENT) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, @@ -120,12 +125,15 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, gboo "Folder `%s' does not exist.", folder_name); goto done; } + printf("creating ...\n"); - if (mkdir (name, 0600) != 0) { + if (mkdir(name, 0700) != 0) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, "Could not create folder `%s':" "\n%s", folder_name, g_strerror(errno)); goto done; } + 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); goto done; @@ -142,13 +150,54 @@ done: static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex) { char *name; + struct stat st; + char *str; name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - "Could not delete folder `%s':\n%s", folder_name, "not implemented"); + if (stat(name, &st) == -1) { + if (errno != ENOENT) + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, + "Could not delete folder `%s': %s", folder_name, strerror(errno)); + } else { + /* this will 'fail' if there are still messages in the directory - + but only the metadata is lost */ + str = g_strdup_printf("%s/ev-summary", name); + unlink(str); + g_free(str); + str = g_strdup_printf("%s/ev-index.ibex", name); + unlink(str); + g_free(str); + if (rmdir(name) == -1) { + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, + "Could not delete folder `%s': %s", folder_name, strerror(errno)); + } + } g_free(name); } +static void rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex) +{ + char *old, *new; + struct stat st; + + old = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, old_name); + new = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, new_name); + if (stat(new, &st) == -1 && errno == ENOENT) { + if (stat(old, &st) == 0 && S_ISDIR(st.st_mode)) { + if (rename(old, new) != 0) { + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, + "Could not rename folder `%s': %s", old_name, strerror(errno)); + } + } else { + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, + "Could not rename folder `%s': %s", old_name, strerror(errno)); + } + } else { + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, + "Could not rename folder `%s': %s exists", old_name, new_name); + } +} + static char *get_folder_name(CamelStore * store, const char *folder_name, CamelException * ex) { /* For now, we don't allow hieararchy. FIXME. */ diff --git a/camel/providers/mh/camel-mh-summary.c b/camel/providers/mh/camel-mh-summary.c index 83f2113..36bfd2f 100644 --- a/camel/providers/mh/camel-mh-summary.c +++ b/camel/providers/mh/camel-mh-summary.c @@ -258,15 +258,17 @@ int camel_mh_summary_sync(CamelMhSummary * mhs, int expunge, CamelException *ex CamelMessageInfo *info; char *name; + printf("summary_sync(expunge=%s)\n", expunge?"true":"false"); + if (!expunge) return 0; count = camel_folder_summary_count((CamelFolderSummary *)mhs); - for (i=0;i=0;i--) { info = camel_folder_summary_index((CamelFolderSummary *)mhs, i); if (info && info->flags & CAMEL_MESSAGE_DELETED) { name = g_strdup_printf("%s/%s", mhs->mh_path, info->uid); - d(printf("deleting %s\n", name)); + (printf("deleting %s\n", name)); if (unlink(name) == 0 || errno==ENOENT) { camel_folder_summary_remove((CamelFolderSummary *)mhs, info); } -- 2.7.4