diff options
Diffstat (limited to 'camel/providers/MH/camel-mh-folder.c')
-rw-r--r-- | camel/providers/MH/camel-mh-folder.c | 1022 |
1 files changed, 0 insertions, 1022 deletions
diff --git a/camel/providers/MH/camel-mh-folder.c b/camel/providers/MH/camel-mh-folder.c deleted file mode 100644 index f4ff8f305a..0000000000 --- a/camel/providers/MH/camel-mh-folder.c +++ /dev/null @@ -1,1022 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-mh-folder.c : Abstract class for an email folder */ - -/* - * - * Copyright (C) 1999 Bertrand Guiheneuf <Bertrand.Guiheneuf@aful.org> . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ -#include <config.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <unistd.h> -#include <sys/types.h> -#include <fcntl.h> -#include <dirent.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include "camel-mh-folder.h" -#include "camel-mh-store.h" -#include "gstring-util.h" -#include "camel-log.h" -#include "camel-stream-fs.h" -#include "camel-stream-buffered-fs.h" -#include "camel-folder-summary.h" -#include "gmime-utils.h" -#include "mh-utils.h" -#include "mh-uid.h" -#include "mh-summary.h" - - -static CamelFolderClass *parent_class=NULL; - -/* Returns the class for a CamelMhFolder */ -#define CMHF_CLASS(so) CAMEL_MH_FOLDER_CLASS (GTK_OBJECT(so)->klass) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (GTK_OBJECT(so)->klass) -#define CMHS_CLASS(so) CAMEL_STORE_CLASS (GTK_OBJECT(so)->klass) - - -static void _set_name(CamelFolder *folder, const gchar *name, CamelException *ex); -static void _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException *ex); -static gboolean _exists (CamelFolder *folder, CamelException *ex); -static gboolean _create(CamelFolder *folder, CamelException *ex); -static gboolean _delete (CamelFolder *folder, gboolean recurse, CamelException *ex); -static gboolean _delete_messages (CamelFolder *folder, CamelException *ex); -static GList *_list_subfolders (CamelFolder *folder, CamelException *ex); -static CamelMimeMessage *_get_message (CamelFolder *folder, gint number, CamelException *ex); -static gint _get_message_count (CamelFolder *folder, CamelException *ex); -static gint _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex); -static void _expunge (CamelFolder *folder, CamelException *ex); -static void _copy_message_to (CamelFolder *folder, CamelMimeMessage *message, CamelFolder *dest_folder, CamelException *ex); -static void _open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex); -static void _close (CamelFolder *folder, gboolean expunge, CamelException *ex); - -static const gchar *_get_message_uid (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex); -static CamelMimeMessage *_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex); -static GList *_get_uid_list (CamelFolder *folder, CamelException *ex); - -/* some utility functions */ -static int copy_reg (const char *src_path, const char *dst_path, CamelException *ex); - -static void -camel_mh_folder_class_init (CamelMhFolderClass *camel_mh_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_mh_folder_class); - - parent_class = gtk_type_class (camel_folder_get_type ()); - - /* virtual method definition */ - /* virtual method overload */ - camel_folder_class->init_with_store = _init_with_store; - camel_folder_class->set_name = _set_name; - camel_folder_class->exists = _exists; - camel_folder_class->delete = _delete; - camel_folder_class->delete_messages = _delete_messages; - camel_folder_class->list_subfolders = _list_subfolders; - camel_folder_class->get_message = _get_message; - camel_folder_class->get_message_count = _get_message_count; - camel_folder_class->append_message = _append_message; - camel_folder_class->expunge = _expunge; - camel_folder_class->copy_message_to = _copy_message_to; - camel_folder_class->open = _open; - camel_folder_class->close = _close; - camel_folder_class->get_message_uid = _get_message_uid; - camel_folder_class->get_message_by_uid = _get_message_by_uid; - camel_folder_class->get_uid_list = _get_uid_list; - -} - - - - - - - -GtkType -camel_mh_folder_get_type (void) -{ - static GtkType camel_mh_folder_type = 0; - - if (!camel_mh_folder_type) { - GtkTypeInfo camel_mh_folder_info = - { - "CamelMhFolder", - sizeof (CamelMhFolder), - sizeof (CamelMhFolderClass), - (GtkClassInitFunc) camel_mh_folder_class_init, - (GtkObjectInitFunc) NULL, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - camel_mh_folder_type = gtk_type_unique (CAMEL_FOLDER_TYPE, &camel_mh_folder_info); - } - - return camel_mh_folder_type; -} - - - -static gint -_message_name_compare (gconstpointer a, gconstpointer b) -{ - gchar *m1 = (gchar *)a; - gchar *m2 = (gchar *)b; - gint len_diff; - - return (atoi (m1) - atoi (m2)); -} - - -static void -_init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException *ex) -{ - /* call parent method */ - parent_class->init_with_store (folder, parent_store, ex); - - folder->can_hold_messages = TRUE; - folder->can_hold_folders = TRUE; - folder->has_summary_capability = TRUE; - folder->has_uid_capability = TRUE; - - folder->summary = NULL; - -} - - - -static void -_open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex) -{ - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER (folder); - struct dirent *dir_entry; - DIR *dir_handle; - - - if (folder->open_state == FOLDER_OPEN) return; - - - /* create message list */ - /* read the whole folder and sort message names */ - dir_handle = opendir (mh_folder->directory_path); - /* read first entry in the directory */ - dir_entry = readdir (dir_handle); - while (dir_entry != NULL) { - /* tests if the entry correspond to a message file */ - if (mh_is_a_message_file (dir_entry->d_name, mh_folder->directory_path)) - /* add the file name to the list */ - mh_folder->file_name_list = g_list_insert_sorted (mh_folder->file_name_list, - g_strdup (dir_entry->d_name), - _message_name_compare); - /* read next entry */ - dir_entry = readdir (dir_handle); - } - - closedir (dir_handle); - - /* get (or create) uid list */ - if (!(mh_load_uid_list (mh_folder) > 0)) - mh_generate_uid_list (mh_folder); - - /* get or create summary */ - /* it is important that it comes after uid list reading/generation */ - if (!(mh_load_summary (mh_folder) > 0)) - mh_generate_summary (folder); - printf ("**** summary = %p\n", folder->summary); - -} - - - -static void -_close (CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER (folder); - - /* save uid list, if any */ - if (mh_folder->uid_array) - mh_save_uid_list (mh_folder); - - /* save summary, if any */ - if (folder->summary) - mh_save_summary (mh_folder); - - /* call parent implementation */ - parent_class->close (folder, expunge, ex); -} - - - - - -/** - * camel_mh_folder_set_name: set the name of an MH folder - * @folder: the folder to set the name - * @name: a string representing the (short) name - * - * - * - **/ -static void -_set_name (CamelFolder *folder, const gchar *name, CamelException *ex) -{ - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER (folder); - const gchar *root_dir_path; - gchar *full_name; - const gchar *parent_full_name; - gchar separator; - - CAMEL_LOG_FULL_DEBUG ("Entering CamelMhFolder::set_name\n"); - g_assert (folder); - g_assert (name); - g_assert (folder->parent_store); - - /* call default implementation */ - parent_class->set_name (folder, name, ex); - - if (mh_folder->directory_path) g_free (mh_folder->directory_path); - - separator = camel_store_get_separator (folder->parent_store); - root_dir_path = camel_mh_store_get_toplevel_dir (CAMEL_MH_STORE(folder->parent_store)); - - CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::set_name full_name is %s\n", folder->full_name); - CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::set_name root_dir_path is %s\n", root_dir_path); - CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::separator is %c\n", separator); - - mh_folder->directory_path = g_strdup_printf ("%s%c%s", root_dir_path, separator, folder->full_name); - - if (!camel_folder_exists (folder, ex)) return; - - - CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::set_name mh_folder->directory_path is %s\n", - mh_folder->directory_path); - CAMEL_LOG_FULL_DEBUG ("Leaving CamelMhFolder::set_name\n"); -} - - - -static gboolean -_exists (CamelFolder *folder, CamelException *ex) -{ - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder); - struct stat stat_buf; - gint stat_error; - gboolean exists; - - CAMEL_LOG_FULL_DEBUG ("Entering CamelMhFolder::exists\n"); - g_assert (folder); - - if (!mh_folder->directory_path) return FALSE; - - stat_error = stat (mh_folder->directory_path, &stat_buf); - if (stat_error == -1) { - CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::exists when executing stat on %s, stat_error = %d\n", - mh_folder->directory_path, stat_error); - CAMEL_LOG_FULL_DEBUG (" Full error text is : %s\n", strerror(errno)); - return FALSE; - } - exists = S_ISDIR (stat_buf.st_mode); - - CAMEL_LOG_FULL_DEBUG ("Leaving CamelMhFolder::exists\n"); - return exists; -} - - -static gboolean -_create (CamelFolder *folder, CamelException *ex) -{ - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder); - const gchar *directory_path; - mode_t dir_mode = S_IRWXU; - gint mkdir_error; - - g_assert(folder); - - /* call default implementation */ - parent_class->create (folder, ex); - - directory_path = mh_folder->directory_path; - if (!directory_path) return FALSE; - - if (camel_folder_exists (folder, ex)) return TRUE; - - mkdir_error = mkdir (directory_path, dir_mode); - return (mkdir_error == -1); -} - - - -static gboolean -_delete (CamelFolder *folder, gboolean recurse, CamelException *ex) -{ - - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder); - const gchar *directory_path; - gint rmdir_error = 0; - - g_assert(folder); - - /* call default implementation */ - parent_class->delete (folder, recurse, ex); - /* the default implementation will care about deleting - messages first and recursing the operation if - necessary */ - - directory_path = mh_folder->directory_path; - if (!directory_path) return FALSE; - - if (!camel_folder_exists (folder, ex)) return TRUE; - - /* physically delete the directory */ - CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::delete removing directory %s\n", directory_path); - rmdir_error = rmdir (directory_path); - if (rmdir_error == -1) { - CAMEL_LOG_WARNING ("CamelMhFolder::delete Error when removing directory %s\n", directory_path); - CAMEL_LOG_FULL_DEBUG ( " Full error text is : %s\n", strerror(errno)); - } - - return (rmdir_error != -1); -} - - -static gboolean -_delete_messages (CamelFolder *folder, CamelException *ex) -{ - - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder); - const gchar *directory_path; - struct stat stat_buf; - gint stat_error = 0; - gchar *entry_name; - struct dirent *dir_entry; - gint unlink_error = 0; - DIR *dir_handle; - - g_assert(folder); - - /* call default implementation */ - parent_class->delete_messages (folder, ex); - - directory_path = mh_folder->directory_path; - if (!directory_path) return FALSE; - - if (!camel_folder_exists (folder, ex)) return TRUE; - - dir_handle = opendir (directory_path); - - /* read first entry in the directory */ - dir_entry = readdir (dir_handle); - while ((stat_error != -1) && (unlink_error != -1) && (dir_entry != NULL)) { - - /* get the name of the next entry in the dir */ - entry_name = dir_entry->d_name; - stat_error = stat (mh_folder->directory_path, &stat_buf); - - /* is it a regular file ? */ - if ((stat_error != -1) && S_ISREG(stat_buf.st_mode)) { - /* yes, delete it */ - CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::delete_messages removing file %s\n", entry_name); - unlink_error = unlink(entry_name); - - if (unlink_error == -1) { - CAMEL_LOG_WARNING ("CamelMhFolder::delete_messages Error when deleting file %s\n", - entry_name); - CAMEL_LOG_FULL_DEBUG ( " Full error text is : %s\n", strerror(errno)); - } - } - /* read next entry */ - dir_entry = readdir (dir_handle); - } - - closedir (dir_handle); - - return ((stat_error != -1) && (unlink_error != -1)); - -} - - - -static GList * -_list_subfolders (CamelFolder *folder, CamelException *ex) -{ - GList *subfolder_name_list = NULL; - - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder); - const gchar *directory_path; - struct stat stat_buf; - gint stat_error = 0; - GList *file_list; - gchar *entry_name; - gchar *full_entry_name; - struct dirent *dir_entry; - DIR *dir_handle; - - g_assert(folder); - - /* call default implementation */ - parent_class->delete_messages (folder, ex); - - directory_path = mh_folder->directory_path; - if (!directory_path) return NULL; - - if (!camel_folder_exists (folder, ex)) return NULL; - - dir_handle = opendir (directory_path); - - /* read first entry in the directory */ - dir_entry = readdir (dir_handle); - while ((stat_error != -1) && (dir_entry != NULL)) { - - /* get the name of the next entry in the dir */ - entry_name = dir_entry->d_name; - full_entry_name = g_strdup_printf ("%s/%s", mh_folder->directory_path, entry_name); - stat_error = stat (full_entry_name, &stat_buf); - g_free (full_entry_name); - - /* is it a directory ? */ - if ((stat_error != -1) && S_ISDIR (stat_buf.st_mode)) { - /* yes, add it to the list */ - if (entry_name[0] != '.') { - CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::list_subfolders adding %s\n", entry_name); - subfolder_name_list = g_list_append (subfolder_name_list, g_strdup (entry_name)); - } - } - /* read next entry */ - dir_entry = readdir (dir_handle); - } - - closedir (dir_handle); - - return subfolder_name_list; -} - - - - - -static void -_filename_free (gpointer data) -{ - g_free ((gchar *)data); -} - - -/* slow routine, may be optimixed, or we should use - caches if users complain */ -static CamelMimeMessage * -_get_message (CamelFolder *folder, gint number, CamelException *ex) -{ - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder); - const gchar *directory_path; - gchar *message_name; - gchar *message_file_name; - CamelStream *input_stream = NULL; - CamelMimeMessage *message = NULL; - GList *message_list = NULL; - - g_assert(folder); - - - directory_path = mh_folder->directory_path; - if (!directory_path) return NULL; - - - - message_name = g_list_nth_data (mh_folder->file_name_list, number); - - if (message_name != NULL) { - CAMEL_LOG_FULL_DEBUG ("CanelMhFolder::get_message message number = %d, name = %s\n", - number, message_name); - message_file_name = g_strdup_printf ("%s/%s", directory_path, message_name); - input_stream = camel_stream_buffered_fs_new_with_name (message_file_name, CAMEL_STREAM_BUFFERED_FS_READ); - - if (input_stream != NULL) { -#warning use session field here - message = camel_mime_message_new (); - camel_data_wrapper_construct_from_stream ( CAMEL_DATA_WRAPPER (message), input_stream); - gtk_object_unref (GTK_OBJECT (input_stream)); - message->message_number = number; - gtk_object_set_data_full (GTK_OBJECT (message), "filename", - g_strdup (message_name), _filename_free); - -#warning Set flags and all this stuff here - } - g_free (message_file_name); - } else - CAMEL_LOG_FULL_DEBUG ("CanelMhFolder::get_message message number = %d, not found\n", number); - - - return message; -} - - - -static gint -_get_message_count (CamelFolder *folder, CamelException *ex) -{ - - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder); - const gchar *directory_path; - struct dirent *dir_entry; - DIR *dir_handle; - guint message_count = 0; - - g_assert(folder); - - directory_path = mh_folder->directory_path; - if (!directory_path) return -1; - - if (!camel_folder_exists (folder, ex)) return 0; - - dir_handle = opendir (directory_path); - - /* read first entry in the directory */ - dir_entry = readdir (dir_handle); - while (dir_entry != NULL) { - /* tests if the entry correspond to a message file */ - if (mh_is_a_message_file (dir_entry->d_name, directory_path)) - message_count++; - /* read next entry */ - dir_entry = readdir (dir_handle); - } - - closedir (dir_handle); - CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::get_message_count found %d messages\n", message_count); - return message_count; -} - - - -static gboolean -_find_next_free_message_file (CamelFolder *folder, gint *new_msg_number, gchar **new_msg_filename, CamelException *ex) -{ - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder); - const gchar *directory_path; - struct dirent *dir_entry; - DIR *dir_handle; - gint last_max_message_number = 0; - gint current_message_number; - - g_assert(folder); - - directory_path = mh_folder->directory_path; - if (!directory_path) return FALSE; - - if (!camel_folder_exists (folder, ex)) return FALSE; - - dir_handle = opendir (directory_path); - - /* read first entry in the directory */ - dir_entry = readdir (dir_handle); - while (dir_entry != NULL) { - /* tests if the entry correspond to a message file */ - if (mh_is_a_message_file (dir_entry->d_name, directory_path)) { - /* see if the message number is the biggest found */ - current_message_number = atoi (dir_entry->d_name); - if (current_message_number > last_max_message_number) - last_max_message_number = current_message_number; - } - /* read next entry */ - dir_entry = readdir (dir_handle); - } - closedir (dir_handle); - - *new_msg_number = last_max_message_number + 1; - *new_msg_filename = g_strdup_printf ("%s/%d", directory_path, *new_msg_number); - CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::find_next_free_message_file new message path is %s\n", - *new_msg_filename); - return TRUE; - - -} -static gint -_append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex) -{ - guint new_msg_number; - gchar *new_msg_filename; - CamelStream *output_stream; - gboolean error; - - CAMEL_LOG_FULL_DEBUG ("Entering CamelMhFolder::append_message\n"); - if (!_find_next_free_message_file (folder, &new_msg_number, &new_msg_filename, ex)) - return -1; - - output_stream = camel_stream_fs_new_with_name (new_msg_filename, CAMEL_STREAM_FS_WRITE); - if (output_stream != NULL) { - camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), output_stream); - camel_stream_close (output_stream); - } else { - CAMEL_LOG_WARNING ("CamelMhFolder::append_message could not open %s for writing\n", - new_msg_filename); - CAMEL_LOG_FULL_DEBUG (" Full error text is : %s\n", strerror(errno)); - error = TRUE; - } - - g_free (new_msg_filename); - CAMEL_LOG_FULL_DEBUG ("Leaving CamelMhFolder::append_message\n"); - if (error) return -1; - else return new_msg_number; -} - - - - - -static void -_expunge (CamelFolder *folder, CamelException *ex) -{ - /* For the moment, we look in the folder active message - * list. I did not make my mind for the moment, should - * the gtk_object->destroy signal be used to expunge - * freed messages objects marked DELETED ? - */ - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder); - CamelMimeMessage *message; - GList *message_node; - gchar *fullpath; - gchar *filename; - gint unlink_error; - const gchar *directory_path; - - CAMEL_LOG_FULL_DEBUG ("Entering CamelFolder::expunge\n"); - - message_node = folder->message_list; - - directory_path = mh_folder->directory_path; - if (!directory_path) return; - - /* look in folder message list which messages - * need to be expunged */ - while ( message_node) { - message = CAMEL_MIME_MESSAGE (message_node->data); - - if (message && camel_mime_message_get_flag (message, "DELETED")) { - CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::expunge, expunging message %d\n", message->message_number); - /* expunge the message */ - filename = gtk_object_get_data (GTK_OBJECT (message), "filename"); - fullpath = g_strdup_printf ("%s/%s", directory_path, filename); - CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::expunge, message fullpath is %s\n", - fullpath); - unlink_error = unlink(fullpath); - if (unlink_error != -1) { - message->expunged = TRUE; - } else { - CAMEL_LOG_WARNING ("CamelMhFolder:: could not unlink %s (message %d)\n", - fullpath, message->message_number); - CAMEL_LOG_FULL_DEBUG (" Full error text is : %s\n", strerror(errno)); - } - } - message_node = message_node->next; - CAMEL_LOG_FULL_DEBUG ("CamelFolder::expunge, examined message node %p\n", message_node); - } - - CAMEL_LOG_FULL_DEBUG ("Leaving CamelFolder::expunge\n"); -} - - -static void -_copy_message_to (CamelFolder *folder, CamelMimeMessage *message, CamelFolder *dest_folder, CamelException *ex) -{ - gchar *src_msg_filename; - guint dest_msg_number; - gchar *dest_msg_filename; - - if (IS_CAMEL_MH_FOLDER (dest_folder)) { - /*g_return_if_fail (message->parent_folder == folder);*/ - - if (!_find_next_free_message_file (dest_folder, &dest_msg_number, &dest_msg_filename, ex)) - return; - src_msg_filename = gtk_object_get_data (GTK_OBJECT (message), "fullpath"); - CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::copy_to copy file %s to %s\n", src_msg_filename, dest_msg_filename); - copy_reg (src_msg_filename, dest_msg_filename, ex); - - } else - parent_class->copy_message_to (folder, message, dest_folder, ex); -} - - - -/** UID **/ - -static const gchar * -_get_message_uid (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex) -{ - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER (folder); - GArray *uid_array; - gboolean found = FALSE; - MhUidCouple *uid_couple; - gchar *filename; - guint file_number; - gint i; - - /* if the message already has its uid stored, - return it */ - if (message->message_uid) - return (message->message_uid); - - /* else, it has a filename associated to it */ - filename = gtk_object_get_data (GTK_OBJECT (message), "filename"); - file_number = atoi (file_number); - - uid_array = mh_folder->uid_array; - uid_couple = (MhUidCouple *)uid_array->data; - - /* look in the uid array for the file number */ - found = (uid_couple->file_number == file_number); - for (i=0; (i<uid_array->len) && (!found); i++) { - uid_couple++; - found = (uid_couple->file_number == file_number); - } - - if (found) return uid_couple->uid; - else return NULL; - -} - - -static CamelMimeMessage * -_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex) -{ - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER (folder); - GArray *uid_array; - gboolean found = FALSE; - MhUidCouple *uid_couple; - gint file_number; - gchar *filename; - CamelMimeMessage *message = NULL; - CamelStream *input_stream; - int i; - - /* - * because they are constructed with md5 - * signatures, all MH uids are 16 bytes long - */ - if (strlen (uid) != 16) return NULL; - - uid_array = mh_folder->uid_array; - uid_couple = (MhUidCouple *)uid_array->data; - - found = !strncmp (uid, uid_couple->uid, 16 * sizeof (guchar)); - for (i=0; (i<uid_array->len) && (!found); i++) { - uid_couple++; - found = !strncmp (uid, uid_couple->uid, 16 * sizeof (guchar)); - } - if (found) { - /* physically retrieve the message */ - file_number = uid_couple->file_number; - filename = g_strdup_printf ("%d", file_number); - input_stream = camel_stream_buffered_fs_new_with_name (filename, CAMEL_STREAM_BUFFERED_FS_READ); - - if (input_stream != NULL) { -#warning use session field here - message = camel_mime_message_new (); - camel_data_wrapper_construct_from_stream ( CAMEL_DATA_WRAPPER (message), input_stream); - gtk_object_unref (GTK_OBJECT (input_stream)); - - /* set message UID in CamelMimeMessage */ - message->message_uid = g_strdup (uid); - - } - g_free (filename); - } - - return message; - -} - -static GList * -_get_uid_list (CamelFolder *folder, CamelException *ex) -{ - CamelMhFolder *mh_folder = CAMEL_MH_FOLDER (folder); - GList *uid_list; - GArray *uid_array; - MhUidCouple *uid_couple; - int i; - - uid_array = mh_folder->uid_array; - uid_couple = (MhUidCouple *)uid_array->data; - - for (i=0; i<uid_array->len; i++) { - uid_list = g_list_prepend (uid_list, uid_couple->uid); - uid_couple++; - } - - return uid_list; -} - - - - - - - - -/************************************************************************/ - -/*** Took directly from GNU fileutils-4.0 ***/ -/* Copyright (C) 89, 90, 91, 95, 96, 97, 1998 Free Software Foundation. */ -/* This may be rwritten soon. -Bertrand */ - - -/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted. - Return LEN upon success, write's (negative) error code otherwise. */ -int -full_write (int desc, const char *ptr, size_t len) -{ - int total_written; - - total_written = 0; - while (len > 0) - { - int written = write (desc, ptr, len); - if (written < 0) - { - if (errno == EINTR) - continue; - return written; - } - total_written += written; - ptr += written; - len -= written; - } - return total_written; -} - - - - -static int -copy_reg (const char *src_path, const char *dst_path, CamelException *ex) -{ - char *buf; - int buf_size; - int dest_desc; - int source_desc; - int n_read; - struct stat sb; - char *cp; - int *ip; - int return_val = 0; - off_t n_read_total = 0; - int last_write_made_hole = 0; - int make_holes = TRUE; - - source_desc = open (src_path, O_RDONLY); - if (source_desc < 0) - { - /* If SRC_PATH doesn't exist, then chances are good that the - user did something like this `cp --backup foo foo': and foo - existed to start with, but copy_internal renamed DST_PATH - with the backup suffix, thus also renaming SRC_PATH. */ - if (errno == ENOENT) - error (0, 0, "`%s' and `%s' are the same file", - src_path, dst_path); - else - error (0, errno, "%s", src_path); - - return -1; - } - - /* Create the new regular file with small permissions initially, - to not create a security hole. */ - - dest_desc = open (dst_path, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (dest_desc < 0) - { - error (0, errno, "cannot create regular file `%s'", dst_path); - return_val = -1; - goto ret2; - } - - /* Find out the optimal buffer size. */ - - if (fstat (dest_desc, &sb)) - { - error (0, errno, "%s", dst_path); - return_val = -1; - goto ret; - } - - buf_size = 8192; - - - - /* Make a buffer with space for a sentinel at the end. */ - - buf = (char *) alloca (buf_size + sizeof (int)); - - for (;;) - { - n_read = read (source_desc, buf, buf_size); - if (n_read < 0) - { - if (errno == EINTR) - continue; - error (0, errno, "%s", src_path); - return_val = -1; - goto ret; - } - if (n_read == 0) - break; - - n_read_total += n_read; - - ip = 0; - if (make_holes) - { - buf[n_read] = 1; /* Sentinel to stop loop. */ - - /* Find first nonzero *word*, or the word with the sentinel. */ - - ip = (int *) buf; - while (*ip++ == 0) - ; - - /* Find the first nonzero *byte*, or the sentinel. */ - - cp = (char *) (ip - 1); - while (*cp++ == 0) - ; - - /* If we found the sentinel, the whole input block was zero, - and we can make a hole. */ - - if (cp > buf + n_read) - { - /* Make a hole. */ - if (lseek (dest_desc, (off_t) n_read, SEEK_CUR) < 0L) - { - error (0, errno, "%s", dst_path); - return_val = -1; - goto ret; - } - last_write_made_hole = 1; - } - else - /* Clear to indicate that a normal write is needed. */ - ip = 0; - } - if (ip == 0) - { - if (full_write (dest_desc, buf, n_read) < 0) - { - error (0, errno, "%s", dst_path); - return_val = -1; - goto ret; - } - last_write_made_hole = 0; - } - } - - /* If the file ends with a `hole', something needs to be written at - the end. Otherwise the kernel would truncate the file at the end - of the last write operation. */ - - if (last_write_made_hole) - { -#if HAVE_FTRUNCATE - /* Write a null character and truncate it again. */ - if (full_write (dest_desc, "", 1) < 0 - || ftruncate (dest_desc, n_read_total) < 0) -#else - /* Seek backwards one character and write a null. */ - if (lseek (dest_desc, (off_t) -1, SEEK_CUR) < 0L - || full_write (dest_desc, "", 1) < 0) -#endif - { - error (0, errno, "%s", dst_path); - return_val = -1; - } - } - -ret: - if (close (dest_desc) < 0) - { - error (0, errno, "%s", dst_path); - return_val = -1; - } -ret2: - if (close (source_desc) < 0) - { - error (0, errno, "%s", src_path); - return_val = -1; - } - - return return_val; -} |