diff options
author | Not Zed <NotZed@HelixCode.com> | 2000-11-16 21:27:21 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2000-11-16 21:27:21 +0800 |
commit | d424adcf6301d996942eef1332f3a61e16b709c2 (patch) | |
tree | 6f6bf5d6aaf3e2bf1eb463458f4f3ac96832874c /camel/providers/local/camel-local-folder.c | |
parent | be8b8b1cea99ef242c42b751c271c579b53ae2e5 (diff) | |
download | gsoc2013-evolution-d424adcf6301d996942eef1332f3a61e16b709c2.tar.gz gsoc2013-evolution-d424adcf6301d996942eef1332f3a61e16b709c2.tar.zst gsoc2013-evolution-d424adcf6301d996942eef1332f3a61e16b709c2.zip |
Check the uid string is all digits before trying to write a 'standard'
2000-11-16 Not Zed <NotZed@HelixCode.com>
* providers/local/camel-local-summary.c
(local_summary_encode_x_evolution): Check the uid string is all
digits before trying to write a 'standard' x-ev header.
* providers/local/camel-maildir-summary.c
(camel_maildir_summary_info_to_name): Convert an info into a
maildir name:info filename.
(camel_maildir_summary_name_to_info): Convert a name:info filename
into an info, and tell us if it didn't match it.
(message_info_new): When creating a new filename, gets its info
from the flags field. Likewise if creating from an existing file,
extract the flags.
(maildir_summary_sync): Remove a small memleak. Also, if our
flags and that requires a filename change, perform that here.
(message_info_new): Get the received date from the filename.
Also, dont overwirte the uid if we have one.
(maildir_summary_check): Sort the summary in received order before
completion.
(maildir_summary_next_uid_string): Test the name for collusions
before we give it out. Retry, and if that fails, well, I guess we
collide :(
* providers/local/camel-mbox-folder.c (mbox_lock): Implement mbox
locking.
(mbox_unlock): And unlocking.
(mbox_append_message): Lock the folder for write before doing
anything.
(mbox_get_message): Lock the folder for read before doing
anything.
* providers/local/camel-local-folder.c (camel_local_folder_lock):
Implement something here. We handle the recursive ability but
pass the locking to the folder itself.
(camel_local_folder_unlock): Likewise for unlocking.
(local_lock): Default - do nothing, return success.
(local_unlock): Same.
(local_sync): Changed slightly for locking api changes, and also,
only lock around the sync process itself.
* camel-lock.c: New file - utility functions for locking using
different strategies and/or for locking folders safely.
* Makefile.am (libcamel_la_SOURCES): Adde camel-lock.[ch]
svn path=/trunk/; revision=6592
Diffstat (limited to 'camel/providers/local/camel-local-folder.c')
-rw-r--r-- | camel/providers/local/camel-local-folder.c | 235 |
1 files changed, 44 insertions, 191 deletions
diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c index 034f91d7ee..bec2d7fb56 100644 --- a/camel/providers/local/camel-local-folder.c +++ b/camel/providers/local/camel-local-folder.c @@ -1,7 +1,5 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* camel-local-folder.c : Abstract class for an email folder */ - -/* +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- + * * Authors: Michael Zucchi <notzed@helixcode.com> * * Copyright (C) 1999, 2000 Helix Code Inc. @@ -53,6 +51,8 @@ static CamelFolderClass *parent_class = NULL; #define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) #define CLOCALS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) +static int local_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); +static void local_unlock(CamelLocalFolder *lf); static void local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex); static gint local_get_message_count(CamelFolder *folder); @@ -111,6 +111,9 @@ camel_local_folder_class_init(CamelLocalFolderClass * camel_local_folder_class) camel_folder_class->set_message_user_flag = local_set_message_user_flag; camel_folder_class->get_message_user_tag = local_get_message_user_tag; camel_folder_class->set_message_user_tag = local_set_message_user_tag; + + camel_local_folder_class->lock = local_lock; + camel_local_folder_class->unlock = local_unlock; } static void @@ -221,36 +224,66 @@ camel_local_folder_construct(CamelLocalFolder *lf, CamelStore *parent_store, con return lf; } -/* Have to work out how/when to lock */ -int camel_local_folder_lock(CamelLocalFolder *lf, CamelException *ex) +/* lock the folder, may be called repeatedly (with matching unlock calls), + with type the same or less than the first call */ +int camel_local_folder_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) +{ + if (lf->locked > 0) { + /* lets be anal here - its important the code knows what its doing */ + g_assert(lf->locktype == type || lf->locktype == CAMEL_LOCK_WRITE); + } else { + if (CLOCALF_CLASS(lf)->lock(lf, type, ex) == -1) + return -1; + lf->locktype = type; + } + + lf->locked++; + + return 0; +} + +/* unlock folder */ +int camel_local_folder_unlock(CamelLocalFolder *lf) { + g_assert(lf->locked>0); + lf->locked--; + if (lf->locked == 0) + CLOCALF_CLASS(lf)->unlock(lf); + return 0; } -int camel_local_folder_unlock(CamelLocalFolder *lf, CamelException *ex) +static int +local_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) { return 0; } static void +local_unlock(CamelLocalFolder *lf) +{ + /* nothing */ +} + +static void local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex) { CamelLocalFolder *lf = CAMEL_LOCAL_FOLDER(folder); d(printf("local sync, expunge=%s\n", expunge?"true":"false")); - if (camel_local_folder_lock(lf, ex) == -1) + if (camel_local_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1) return; + /* if sync fails, we'll pass it up on exit through ex */ camel_local_summary_sync(lf->summary, expunge, lf->changes, ex); + camel_local_folder_unlock(lf); + if (camel_folder_change_info_changed(lf->changes)) { camel_object_trigger_event(CAMEL_OBJECT(folder), "folder_changed", lf->changes); camel_folder_change_info_clear(lf->changes); } - if (camel_local_folder_unlock(lf, ex) == -1) - return; - /* force save of metadata */ if (lf->index) ibex_save(lf->index); @@ -267,186 +300,6 @@ local_expunge(CamelFolder *folder, CamelException *ex) camel_folder_sync(folder, TRUE, ex); } -#if 0 -static void -local_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, CamelException *ex) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - CamelStream *output_stream = NULL, *filter_stream = NULL; - CamelMimeFilter *filter_from = NULL; - CamelMessageInfo *newinfo; - struct stat st; - off_t seek = -1; - char *xev; - guint32 uid; - char *fromline = NULL; - - if (stat(local_folder->folder_path, &st) != 0) - goto fail; - - output_stream = camel_stream_fs_new_with_name(local_folder->folder_file_path, O_WRONLY|O_APPEND, 0600); - if (output_stream == NULL) - goto fail; - - seek = st.st_size; - - /* assign a new x-evolution header/uid */ - camel_medium_remove_header(CAMEL_MEDIUM(message), "X-Evolution"); - uid = camel_folder_summary_next_uid(CAMEL_FOLDER_SUMMARY(local_folder->summary)); - /* important that the header matches exactly 00000000-0000 */ - xev = g_strdup_printf("%08x-%04x", uid, info ? info->flags & 0xFFFF : 0); - camel_medium_add_header(CAMEL_MEDIUM(message), "X-Evolution", xev); - g_free(xev); - - /* we must write this to the non-filtered stream ... */ - fromline = camel_local_summary_build_from(CAMEL_MIME_PART(message)->headers); - if (camel_stream_printf(output_stream, seek==0?"%s":"\n%s", fromline) == -1) - goto fail; - - /* and write the content to the filtering stream, that translated '\nFrom' into '\n>From' */ - filter_stream = (CamelStream *) camel_stream_filter_new_with_stream(output_stream); - filter_from = (CamelMimeFilter *) camel_mime_filter_from_new(); - camel_stream_filter_add((CamelStreamFilter *) filter_stream, filter_from); - if (camel_data_wrapper_write_to_stream(CAMEL_DATA_WRAPPER(message), filter_stream) == -1) - goto fail; - - if (camel_stream_close(filter_stream) == -1) - goto fail; - - /* filter stream ref's the output stream itself, so we need to unref it too */ - camel_object_unref(CAMEL_OBJECT(filter_from)); - camel_object_unref(CAMEL_OBJECT(filter_stream)); - camel_object_unref(CAMEL_OBJECT(output_stream)); - g_free(fromline); - - /* force a summary update - will only update from the new position, if it can */ - if (camel_local_summary_update(local_folder->summary, seek==0?seek:seek+1, local_folder->changes) == 0) { - char uidstr[16]; - - sprintf(uidstr, "%u", uid); - newinfo = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(local_folder->summary), uidstr); - - if (info && newinfo) { - CamelFlag *flag = info->user_flags; - CamelTag *tag = info->user_tags; - - while (flag) { - camel_flag_set(&(newinfo->user_flags), flag->name, TRUE); - flag = flag->next; - } - - while (tag) { - camel_tag_set(&(newinfo->user_tags), tag->name, tag->value); - tag = tag->next; - } - } - camel_object_trigger_event(CAMEL_OBJECT(folder), "folder_changed", local_folder->changes); - camel_folder_change_info_clear(local_folder->changes); - } - - return; - - fail: - if (camel_exception_is_set(ex)) { - camel_exception_setv(ex, camel_exception_get_id(ex), - _("Cannot append message to local file: %s"), camel_exception_get_description(ex)); - } else { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to local file: %s"), g_strerror(errno)); - } - if (filter_stream) { - /*camel_stream_close (filter_stream); */ - camel_object_unref(CAMEL_OBJECT(filter_stream)); - } - if (output_stream) - camel_object_unref(CAMEL_OBJECT(output_stream)); - - if (filter_from) - camel_object_unref(CAMEL_OBJECT(filter_from)); - - g_free(fromline); - - /* make sure the file isn't munged by us */ - if (seek != -1) { - int fd = open(local_folder->folder_file_path, O_WRONLY, 0600); - - if (fd != -1) { - ftruncate(fd, st.st_size); - close(fd); - } - } -} - -static CamelMimeMessage * -local_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - CamelStream *message_stream = NULL; - CamelMimeMessage *message = NULL; - CamelLocalMessageInfo *info; - CamelMimeParser *parser = NULL; - char *buffer; - int len; - - /* get the message summary info */ - info = (CamelLocalMessageInfo *) camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(local_folder->summary), uid); - - if (info == NULL) { - errno = ENOENT; - goto fail; - } - - /* if this has no content, its an error in the library */ - g_assert(info->info.content); - g_assert(info->frompos != -1); - - /* where we read from */ - message_stream = camel_stream_fs_new_with_name(local_folder->folder_file_path, O_RDONLY, 0); - if (message_stream == NULL) - goto fail; - - /* we use a parser to verify the message is correct, and in the correct position */ - parser = camel_mime_parser_new(); - camel_mime_parser_init_with_stream(parser, message_stream); - camel_object_unref(CAMEL_OBJECT(message_stream)); - camel_mime_parser_scan_from(parser, TRUE); - - camel_mime_parser_seek(parser, info->frompos, SEEK_SET); - if (camel_mime_parser_step(parser, &buffer, &len) != HSCAN_FROM) { - g_warning("File appears truncated"); - goto fail; - } - - if (camel_mime_parser_tell_start_from(parser) != info->frompos) { - /* TODO: This should probably perform a re-sync/etc, and try again? */ - g_warning("Summary doesn't match the folder contents! eek!\n" - " expecting offset %ld got %ld", (long int)info->frompos, - (long int)camel_mime_parser_tell_start_from(parser)); - errno = EINVAL; - goto fail; - } - - message = camel_mime_message_new(); - if (camel_mime_part_construct_from_parser(CAMEL_MIME_PART(message), parser) == -1) { - g_warning("Construction failed"); - goto fail; - } - camel_object_unref(CAMEL_OBJECT(parser)); - - return message; - - fail: - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s"), g_strerror(errno)); - - if (parser) - camel_object_unref(CAMEL_OBJECT(parser)); - if (message) - camel_object_unref(CAMEL_OBJECT(message)); - - return NULL; -} -#endif - /* The following functions all work off the summary, so the default operations provided in camel-local-folder will suffice for all subclasses. They may want to |