author | zautrix <zautrix> | 2004-12-04 14:45:53 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-12-04 14:45:53 (UTC) |
commit | b417f02504c962f692dad0b5e043243193b9f871 (patch) (side-by-side diff) | |
tree | 0bd35e0916be791f5c21c012a0ad9ba9326857f9 /kmicromail/libetpan/mh/mailmh.c | |
parent | a3b1470f3da722d044505f78bef9de51b2107802 (diff) | |
download | kdepimpi-b417f02504c962f692dad0b5e043243193b9f871.zip kdepimpi-b417f02504c962f692dad0b5e043243193b9f871.tar.gz kdepimpi-b417f02504c962f692dad0b5e043243193b9f871.tar.bz2 |
comments added
Diffstat (limited to 'kmicromail/libetpan/mh/mailmh.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | kmicromail/libetpan/mh/mailmh.c | 473 |
1 files changed, 239 insertions, 234 deletions
diff --git a/kmicromail/libetpan/mh/mailmh.c b/kmicromail/libetpan/mh/mailmh.c index 5e2b4cc..1087ce1 100644 --- a/kmicromail/libetpan/mh/mailmh.c +++ b/kmicromail/libetpan/mh/mailmh.c @@ -1,985 +1,990 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - DINH Viet Hoa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the libEtPan! project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id$ */ #include "mailmh.h" /* perfs : /net/home/dinh/Mail/inbox/sylpheed 686 2724 /net/home/dinh/Mail/inbox/sylpheed bart:~/LibEtPan/libetpan/tests> time ./mhtest >/dev/null real 0m0.385s user 0m0.270s sys 0m0.110s */ #include <dirent.h> #include <sys/stat.h> #include <errno.h> #include <unistd.h> #include <sys/mman.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "libetpan-config.h" struct mailmh * mailmh_new(const char * foldername) { struct mailmh * f; f = malloc(sizeof(*f)); if (f == NULL) return NULL; f->mh_main = mailmh_folder_new(NULL, foldername); if (f->mh_main == NULL) { free(f); return NULL; } return f; } void mailmh_free(struct mailmh * f) { mailmh_folder_free(f->mh_main); free(f); } struct mailmh_msg_info * mailmh_msg_info_new(uint32_t index, size_t size, time_t mtime) { struct mailmh_msg_info * msg_info; msg_info = malloc(sizeof(* msg_info)); if (msg_info == NULL) return NULL; msg_info->msg_index = index; msg_info->msg_size = size; msg_info->msg_mtime = mtime; msg_info->msg_array_index = 0; return msg_info; } void mailmh_msg_info_free(struct mailmh_msg_info * msg_info) { free(msg_info); } struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent, const char * name) { char * filename; char * parent_filename; struct mailmh_folder * folder; folder = malloc(sizeof(* folder)); if (folder == NULL) goto err; if (parent == NULL) { filename = strdup(name); if (filename == NULL) goto free_folder; } else { parent_filename = parent->fl_filename; filename = malloc(strlen(parent_filename) + strlen(name) + 2); if (filename == NULL) goto free_folder; strcpy(filename, parent_filename); strcat(filename, MAIL_DIR_SEPARATOR_S); strcat(filename, name); } folder->fl_filename = filename; folder->fl_name = strdup(name); if (folder->fl_name == NULL) goto free_filename; folder->fl_msgs_tab = carray_new(128); if (folder->fl_msgs_tab == NULL) goto free_name; #if 0 folder->fl_msgs_hash = cinthash_new(128); if (folder->fl_msgs_hash == NULL) goto free_msgs_tab; #endif folder->fl_msgs_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); if (folder->fl_msgs_hash == NULL) goto free_msgs_tab; folder->fl_subfolders_tab = carray_new(128); if (folder->fl_subfolders_tab == NULL) goto free_msgs_hash; folder->fl_subfolders_hash = chash_new(128, CHASH_COPYNONE); if (folder->fl_subfolders_hash == NULL) goto free_subfolders_tab; folder->fl_mtime = 0; folder->fl_parent = parent; folder->fl_max_index = 0; return folder; free_subfolders_tab: carray_free(folder->fl_subfolders_tab); free_msgs_hash: #if 0 cinthash_free(folder->fl_msgs_hash); #endif chash_free(folder->fl_msgs_hash); free_msgs_tab: carray_free(folder->fl_msgs_tab); free_name: free(folder->fl_name); free_filename: free(folder->fl_filename); free_folder: free(folder); err: return NULL; } void mailmh_folder_free(struct mailmh_folder * folder) { unsigned int i; for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) { struct mailmh_folder * subfolder; subfolder = carray_get(folder->fl_subfolders_tab, i); if (subfolder != NULL) mailmh_folder_free(subfolder); } carray_free(folder->fl_subfolders_tab); chash_free(folder->fl_subfolders_hash); for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { struct mailmh_msg_info * msg_info; msg_info = carray_get(folder->fl_msgs_tab, i); if (msg_info != NULL) mailmh_msg_info_free(msg_info); } carray_free(folder->fl_msgs_tab); chash_free(folder->fl_msgs_hash); #if 0 cinthash_free(folder->fl_msgs_hash); #endif free(folder->fl_filename); free(folder->fl_name); free(folder); } struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root, const char * filename) { int r; char pathname[PATH_MAX]; char * p; chashdatum key; chashdatum data; struct mailmh_folder * folder; char * start; if (strcmp(root->fl_filename, filename) == 0) return root; #if 0 r = mailmh_folder_update(root); if (r != MAILMH_NO_ERROR) return NULL; #endif #if 0 for(i = 0 ; i < root->fl_subfolders_tab->len ; i++) { struct mailmh_folder * subfolder; subfolder = carray_get(root->fl_subfolders_tab, i); if (subfolder != NULL) if (strncmp(subfolder->fl_filename, filename, strlen(subfolder->fl_filename)) == 0) return mailmh_folder_find(subfolder, filename); } #endif strncpy(pathname, filename, PATH_MAX); pathname[PATH_MAX - 1] = 0; start = pathname + strlen(root->fl_filename) + 1; p = strchr(start, MAIL_DIR_SEPARATOR); if (p != NULL) { * p = 0; root = mailmh_folder_find(root, pathname); if (root != NULL) { folder = mailmh_folder_find(root, filename); if (folder == NULL) return NULL; return folder; } return NULL; } else { key.data = pathname; key.len = strlen(pathname); r = chash_get(root->fl_subfolders_hash, &key, &data); if (r < 0) return NULL; return data.data; } } int mailmh_folder_update(struct mailmh_folder * folder) { - DIR * d; - struct dirent * ent; - struct stat buf; - char * mh_seq; - char filename[PATH_MAX]; - int res; - int r; - uint32_t max_index; + DIR * d; + struct dirent * ent; + struct stat buf; + char * mh_seq; + char filename[PATH_MAX]; + int res; + int r; + uint32_t max_index; #if 0 - int add_folder; + int add_folder; #endif - unsigned int i; + unsigned int i; - if (stat(folder->fl_filename, &buf) == -1) { - res = MAILMH_ERROR_FOLDER; - goto err; - } + if (stat(folder->fl_filename, &buf) == -1) { + res = MAILMH_ERROR_FOLDER; + goto err; + } - if (folder->fl_mtime == buf.st_mtime) { - res = MAILMH_NO_ERROR; - goto err; - } + if (folder->fl_mtime == buf.st_mtime) { + res = MAILMH_NO_ERROR; + goto err; + } - folder->fl_mtime = buf.st_mtime; + folder->fl_mtime = buf.st_mtime; - d = opendir(folder->fl_filename); - if (d == NULL) { - res = MAILMH_ERROR_FOLDER; - goto err; - } + d = opendir(folder->fl_filename); + if (d == NULL) { + res = MAILMH_ERROR_FOLDER; + goto err; + } - max_index = 0; + max_index = 0; #if 0 - if (folder->fl_subfolders_tab->len == 0) - add_folder = 1; - else - add_folder = 0; + if (folder->fl_subfolders_tab->len == 0) + add_folder = 1; + else + add_folder = 0; #endif - /* clear the message list */ + /* clear the message list */ - for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) { - struct mailmh_msg_info * msg_info; - chashdatum key; + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) { + struct mailmh_msg_info * msg_info; + chashdatum key; - msg_info = carray_get(folder->fl_msgs_tab, i); - if (msg_info == NULL) - continue; + msg_info = carray_get(folder->fl_msgs_tab, i); + if (msg_info == NULL) + continue; #if 0 - cinthash_remove(folder->fl_msgs_hash, msg_info->msg_index); + cinthash_remove(folder->fl_msgs_hash, msg_info->msg_index); #endif - key.data = &msg_info->msg_index; - key.len = sizeof(msg_info->msg_index); - chash_delete(folder->fl_msgs_hash, &key, NULL); + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + chash_delete(folder->fl_msgs_hash, &key, NULL); - mailmh_msg_info_free(msg_info); - } + mailmh_msg_info_free(msg_info); + } - carray_set_size(folder->fl_msgs_tab, 0); + carray_set_size(folder->fl_msgs_tab, 0); - do { - uint32_t index; + do { + uint32_t index; - ent = readdir(d); + ent = readdir(d); - if (ent != NULL) { + if (ent != NULL) { - snprintf(filename, PATH_MAX, - "%s%c%s", folder->fl_filename, MAIL_DIR_SEPARATOR, ent->d_name); + snprintf(filename, PATH_MAX, + "%s%c%s", folder->fl_filename, MAIL_DIR_SEPARATOR, ent->d_name); - if (stat(filename, &buf) == -1) - continue; + if (stat(filename, &buf) == -1) + continue; - if (S_ISREG(buf.st_mode)) { - index = strtoul(ent->d_name, NULL, 10); - if (index != 0) { - struct mailmh_msg_info * msg_info; - unsigned int array_index; - chashdatum key; - chashdatum data; + if (S_ISREG(buf.st_mode)) { + index = strtoul(ent->d_name, NULL, 10); + if (index != 0) { + struct mailmh_msg_info * msg_info; + unsigned int array_index; + chashdatum key; + chashdatum data; - msg_info = mailmh_msg_info_new(index, buf.st_size, buf.st_mtime); - if (msg_info == NULL) { - res = MAILMH_ERROR_MEMORY; - goto closedir; - } + msg_info = mailmh_msg_info_new(index, buf.st_size, buf.st_mtime); + if (msg_info == NULL) { + res = MAILMH_ERROR_MEMORY; + goto closedir; + } - r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); - if (r < 0) { - mailmh_msg_info_free(msg_info); - res = MAILMH_ERROR_MEMORY; - goto closedir; - } - msg_info->msg_array_index = array_index; + r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); + if (r < 0) { + mailmh_msg_info_free(msg_info); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + msg_info->msg_array_index = array_index; - if (index > max_index) - max_index = index; + if (index > max_index) + max_index = index; #if 0 - r = cinthash_add(folder->fl_msgs_hash, msg_info->msg_index, msg_info); + r = cinthash_add(folder->fl_msgs_hash, msg_info->msg_index, msg_info); #endif - key.data = &msg_info->msg_index; - key.len = sizeof(msg_info->msg_index); - data.data = msg_info; - data.len = 0; + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + data.data = msg_info; + data.len = 0; - r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); - if (r < 0) { - carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); - mailmh_msg_info_free(msg_info); - res = MAILMH_ERROR_MEMORY; - goto closedir; - } - } - } - else if (S_ISDIR(buf.st_mode)) { - struct mailmh_folder * subfolder; - unsigned int array_index; - chashdatum key; - chashdatum data; - - if (ent->d_name[0] == '.') { - if (ent->d_name[1] == 0) - continue; - if ((ent->d_name[1] == '.') && (ent->d_name[2] == 0)) - continue; - } - - key.data = ent->d_name; - key.len = strlen(ent->d_name); - r = chash_get(folder->fl_subfolders_hash, &key, &data); - if (r < 0) { - subfolder = mailmh_folder_new(folder, ent->d_name); - if (subfolder == NULL) { - res = MAILMH_ERROR_MEMORY; - goto closedir; - } + r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); + mailmh_msg_info_free(msg_info); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + //LR memory leak? added next line + //mailmh_msg_info_free(msg_info); + //it seems so that it should be freed later, + // but it is not in every case + //PENDING fixme in ompi somewhere + } + } + else if (S_ISDIR(buf.st_mode)) { + struct mailmh_folder * subfolder; + unsigned int array_index; + chashdatum key; + chashdatum data; + + if (ent->d_name[0] == '.') { + if (ent->d_name[1] == 0) + continue; + if ((ent->d_name[1] == '.') && (ent->d_name[2] == 0)) + continue; + } + + key.data = ent->d_name; + key.len = strlen(ent->d_name); + r = chash_get(folder->fl_subfolders_hash, &key, &data); + if (r < 0) { + subfolder = mailmh_folder_new(folder, ent->d_name); + if (subfolder == NULL) { + res = MAILMH_ERROR_MEMORY; + goto closedir; + } - r = carray_add(folder->fl_subfolders_tab, subfolder, &array_index); - if (r < 0) { - mailmh_folder_free(subfolder); - res = MAILMH_ERROR_MEMORY; - goto closedir; - } - subfolder->fl_array_index = array_index; + r = carray_add(folder->fl_subfolders_tab, subfolder, &array_index); + if (r < 0) { + mailmh_folder_free(subfolder); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + subfolder->fl_array_index = array_index; - key.data = subfolder->fl_filename; - key.len = strlen(subfolder->fl_filename); - data.data = subfolder; - data.len = 0; - r = chash_set(folder->fl_subfolders_hash, &key, &data, NULL); - if (r < 0) { - carray_delete_fast(folder->fl_subfolders_tab, subfolder->fl_array_index); - mailmh_folder_free(subfolder); - res = MAILMH_ERROR_MEMORY; - goto closedir; - } - } - } + key.data = subfolder->fl_filename; + key.len = strlen(subfolder->fl_filename); + data.data = subfolder; + data.len = 0; + r = chash_set(folder->fl_subfolders_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_subfolders_tab, subfolder->fl_array_index); + mailmh_folder_free(subfolder); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + } + } + } } - } - while (ent != NULL); + while (ent != NULL); - folder->fl_max_index = max_index; + folder->fl_max_index = max_index; - mh_seq = malloc(strlen(folder->fl_filename) + 2 + sizeof(".mh_sequences")); - if (mh_seq == NULL) { - res = MAILMH_ERROR_MEMORY; - goto closedir; - } - strcpy(mh_seq, folder->fl_filename); - strcat(mh_seq, MAIL_DIR_SEPARATOR_S); - strcat(mh_seq, ".mh_sequences"); + mh_seq = malloc(strlen(folder->fl_filename) + 2 + sizeof(".mh_sequences")); + if (mh_seq == NULL) { + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + strcpy(mh_seq, folder->fl_filename); + strcat(mh_seq, MAIL_DIR_SEPARATOR_S); + strcat(mh_seq, ".mh_sequences"); - if (stat(mh_seq, &buf) == -1) { - int fd; + if (stat(mh_seq, &buf) == -1) { + int fd; - fd = creat(mh_seq, S_IRUSR | S_IWUSR); - if (fd != -1) - close(fd); - } - free(mh_seq); + fd = creat(mh_seq, S_IRUSR | S_IWUSR); + if (fd != -1) + close(fd); + } + free(mh_seq); - closedir(d); + closedir(d); - return MAILMH_NO_ERROR; + return MAILMH_NO_ERROR; closedir: - closedir(d); + closedir(d); err: - return res; + return res; } int mailmh_folder_add_subfolder(struct mailmh_folder * parent, - const char * name) + const char * name) { - char * foldername; - int r; - struct mailmh_folder * folder; - unsigned int array_index; - chashdatum key; - chashdatum data; + char * foldername; + int r; + struct mailmh_folder * folder; + unsigned int array_index; + chashdatum key; + chashdatum data; - foldername = malloc(strlen(parent->fl_filename) + strlen(name) + 2); - if (foldername == NULL) - return MAILMH_ERROR_MEMORY; - strcpy(foldername, parent->fl_filename); - strcat(foldername, MAIL_DIR_SEPARATOR_S); - strcat(foldername, name); + foldername = malloc(strlen(parent->fl_filename) + strlen(name) + 2); + if (foldername == NULL) + return MAILMH_ERROR_MEMORY; + strcpy(foldername, parent->fl_filename); + strcat(foldername, MAIL_DIR_SEPARATOR_S); + strcat(foldername, name); - r = mkdir(foldername, 0700); - free(foldername); + r = mkdir(foldername, 0700); + free(foldername); - if (r < 0) - return MAILMH_ERROR_FOLDER; + if (r < 0) + return MAILMH_ERROR_FOLDER; - folder = mailmh_folder_new(parent, name); - if (folder == NULL) - return MAILMH_ERROR_MEMORY; + folder = mailmh_folder_new(parent, name); + if (folder == NULL) + return MAILMH_ERROR_MEMORY; - r = carray_add(parent->fl_subfolders_tab, folder, &array_index); - if (r < 0) { - mailmh_folder_free(folder); - return MAILMH_ERROR_MEMORY; - } - folder->fl_array_index = array_index; - - key.data = folder->fl_filename; - key.len = strlen(folder->fl_filename); - data.data = folder; - data.len = 0; - - r = chash_set(parent->fl_subfolders_hash, &key, &data, NULL); - if (r < 0) { - carray_delete_fast(folder->fl_subfolders_tab, folder->fl_array_index); - mailmh_folder_free(folder); - return MAILMH_ERROR_MEMORY; - } + r = carray_add(parent->fl_subfolders_tab, folder, &array_index); + if (r < 0) { + mailmh_folder_free(folder); + return MAILMH_ERROR_MEMORY; + } + folder->fl_array_index = array_index; + + key.data = folder->fl_filename; + key.len = strlen(folder->fl_filename); + data.data = folder; + data.len = 0; + + r = chash_set(parent->fl_subfolders_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_subfolders_tab, folder->fl_array_index); + mailmh_folder_free(folder); + return MAILMH_ERROR_MEMORY; + } - return MAILMH_NO_ERROR; + return MAILMH_NO_ERROR; } int mailmh_folder_remove_subfolder(struct mailmh_folder * folder) { - struct mailmh_folder * parent; - chashdatum key; - chashdatum data; - int r; + struct mailmh_folder * parent; + chashdatum key; + chashdatum data; + int r; - parent = folder->fl_parent; + parent = folder->fl_parent; - key.data = folder->fl_filename; - key.len = strlen(folder->fl_filename); + key.data = folder->fl_filename; + key.len = strlen(folder->fl_filename); - r = chash_get(parent->fl_subfolders_hash, &key, &data); - if (r < 0) - return MAILMH_ERROR_FOLDER; + r = chash_get(parent->fl_subfolders_hash, &key, &data); + if (r < 0) + return MAILMH_ERROR_FOLDER; - chash_delete(parent->fl_subfolders_hash, &key, NULL); - carray_delete_fast(parent->fl_subfolders_tab, folder->fl_array_index); + chash_delete(parent->fl_subfolders_hash, &key, NULL); + carray_delete_fast(parent->fl_subfolders_tab, folder->fl_array_index); - mailmh_folder_free(folder); + mailmh_folder_free(folder); - return MAILMH_NO_ERROR; + return MAILMH_NO_ERROR; } int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder, - struct mailmh_folder * dst_folder, - const char * new_name) + struct mailmh_folder * dst_folder, + const char * new_name) { - int r; - struct mailmh_folder * folder; - struct mailmh_folder * parent; - char * new_foldername; + int r; + struct mailmh_folder * folder; + struct mailmh_folder * parent; + char * new_foldername; - parent = src_folder->fl_parent; - if (parent == NULL) - return MAILMH_ERROR_RENAME; + parent = src_folder->fl_parent; + if (parent == NULL) + return MAILMH_ERROR_RENAME; - new_foldername = malloc(strlen(dst_folder->fl_filename) + 2 + strlen(new_name)); - if (new_foldername == NULL) - return MAILMH_ERROR_MEMORY; + new_foldername = malloc(strlen(dst_folder->fl_filename) + 2 + strlen(new_name)); + if (new_foldername == NULL) + return MAILMH_ERROR_MEMORY; - strcpy(new_foldername, dst_folder->fl_filename); - strcat(new_foldername, MAIL_DIR_SEPARATOR_S); - strcat(new_foldername, new_name); + strcpy(new_foldername, dst_folder->fl_filename); + strcat(new_foldername, MAIL_DIR_SEPARATOR_S); + strcat(new_foldername, new_name); - r = rename(src_folder->fl_filename, new_foldername); - free(new_foldername); - if (r < 0) - return MAILMH_ERROR_RENAME; + r = rename(src_folder->fl_filename, new_foldername); + free(new_foldername); + if (r < 0) + return MAILMH_ERROR_RENAME; - r = mailmh_folder_remove_subfolder(src_folder); - if (r != MAILMH_NO_ERROR) - return r; + r = mailmh_folder_remove_subfolder(src_folder); + if (r != MAILMH_NO_ERROR) + return r; - folder = mailmh_folder_new(dst_folder, new_name); - if (folder == NULL) - return MAILMH_ERROR_MEMORY; + folder = mailmh_folder_new(dst_folder, new_name); + if (folder == NULL) + return MAILMH_ERROR_MEMORY; - r = carray_add(parent->fl_subfolders_tab, folder, NULL); - if (r < 0) { - mailmh_folder_free(folder); - return MAILMH_ERROR_MEMORY; - } + r = carray_add(parent->fl_subfolders_tab, folder, NULL); + if (r < 0) { + mailmh_folder_free(folder); + return MAILMH_ERROR_MEMORY; + } - return MAILMH_NO_ERROR; + return MAILMH_NO_ERROR; } #define MAX_TRY_ALLOC 32 /* initial file MUST be in the same directory */ static int mailmh_folder_alloc_msg(struct mailmh_folder * folder, char * filename, uint32_t * result) { uint32_t max; uint32_t k; char * new_filename; size_t len; struct stat f_stat; len = strlen(folder->fl_filename) + 20; new_filename = malloc(len); if (new_filename == NULL) return MAILMH_ERROR_MEMORY; max = folder->fl_max_index + 1; //fprintf(stderr,"mailmh_folder_alloc_msg filename: %s \n", filename); k = 0; while (k < MAX_TRY_ALLOC) { snprintf(new_filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR, (unsigned long) (max + k)); //fprintf(stderr,"mailmh_folder_alloc_msg new_filename: %s \n", new_filename); if ( stat( new_filename, &f_stat ) == -1 ) { // if (link(filename, new_filename) == 0) { int r; //fprintf(stderr,"filename found \n"); //unlink(filename); rename (filename,new_filename ); free(new_filename); if (k > MAX_TRY_ALLOC / 2) { r = mailmh_folder_update(folder); /* ignore errors */ } * result = max + k; folder->fl_max_index = max + k; return MAILMH_NO_ERROR; } else if (errno == EXDEV) { free(filename); return MAILMH_ERROR_FOLDER; } k ++; } free(new_filename); return MAILMH_ERROR_FOLDER; } int mailmh_folder_get_message_filename(struct mailmh_folder * folder, uint32_t index, char ** result) { char * filename; int len; #if 0 r = mailmh_folder_update(folder); if (r != MAILMH_NO_ERROR) return r; #endif len = strlen(folder->fl_filename) + 20; filename = malloc(len); if (filename == NULL) return MAILMH_ERROR_MEMORY; snprintf(filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR, (unsigned long) index); * result = filename; return MAILMH_NO_ERROR;; } int mailmh_folder_get_message_fd(struct mailmh_folder * folder, uint32_t index, int flags, int * result) { char * filename; int fd; int r; #if 0 r = mailmh_folder_update(folder); if (r != MAILMH_NO_ERROR) return r; #endif r = mailmh_folder_get_message_filename(folder, index, &filename); if (r != MAILMH_NO_ERROR) return r; fd = open(filename, flags); free(filename); if (fd == -1) return MAILMH_ERROR_MSG_NOT_FOUND; * result = fd; return MAILMH_NO_ERROR; } int mailmh_folder_get_message_size(struct mailmh_folder * folder, uint32_t index, size_t * result) { int r; char * filename; struct stat buf; r = mailmh_folder_get_message_filename(folder, index, &filename); if (r != MAILMH_NO_ERROR) return r; r = stat(filename, &buf); free(filename); if (r < 0) return MAILMH_ERROR_FILE; * result = buf.st_size; return MAILMH_NO_ERROR; } int mailmh_folder_add_message_uid(struct mailmh_folder * folder, const char * message, size_t size, uint32_t * pindex) { char * tmpname; int fd; size_t namesize; size_t left; ssize_t res; struct mailmh_msg_info * msg_info; uint32_t index; int error; int r; unsigned int array_index; struct stat buf; chashdatum key; chashdatum data; #if 0 r = mailmh_folder_update(folder); if (r != MAILMH_NO_ERROR) { error = r; goto err; } #endif namesize = strlen(folder->fl_filename) + 20; tmpname = malloc(namesize); snprintf(tmpname, namesize, "%s%ctmpXXXXXX", folder->fl_filename, MAIL_DIR_SEPARATOR); fd = mkstemp(tmpname); if (fd < 0) { error = MAILMH_ERROR_FILE; goto free; } left = size; while (left > 0) { res = write(fd, message, left); if (res == -1) { close(fd); error = MAILMH_ERROR_FILE; goto free; } left -= res; } close(fd); r = stat(tmpname, &buf); if (r < 0) { error = MAILMH_ERROR_FILE; goto free; } r = mailmh_folder_alloc_msg(folder, tmpname, &index); if (r != MAILMH_NO_ERROR) { unlink(tmpname); error = MAILMH_ERROR_COULD_NOT_ALLOC_MSG; goto free; } free(tmpname); msg_info = mailmh_msg_info_new(index, size, buf.st_mtime); if (msg_info == NULL) { mailmh_folder_remove_message(folder, index); error = MAILMH_ERROR_MEMORY; goto err; } r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); if (r < 0) { mailmh_folder_remove_message(folder, index); mailmh_msg_info_free(msg_info); error = MAILMH_ERROR_MEMORY; goto err; } msg_info->msg_array_index = array_index; #if 0 r = cinthash_add(folder->fl_msgs_hash, index, msg_info); #endif key.data = &index; key.len = sizeof(index); data.data = msg_info; data.len = 0; if (pindex != NULL) * pindex = index; r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); if (r < 0) { carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); mailmh_msg_info_free(msg_info); error = MAILMH_ERROR_MEMORY; goto err; } return MAILMH_NO_ERROR; free: free(tmpname); err: return error; } int mailmh_folder_add_message(struct mailmh_folder * folder, const char * message, size_t size) { return mailmh_folder_add_message_uid(folder, message, size, NULL); } int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder, int fd, uint32_t * pindex) { char * message; struct stat buf; int r; #if 0 r = mailmh_folder_update(folder); if (r != MAILMH_NO_ERROR) return r; #endif if (fstat(fd, &buf) == -1) return MAILMH_ERROR_FILE; message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (message == MAP_FAILED) return MAILMH_ERROR_FILE; r = mailmh_folder_add_message_uid(folder, message, buf.st_size, pindex); munmap(message, buf.st_size); return r; } int mailmh_folder_add_message_file(struct mailmh_folder * folder, int fd) { return mailmh_folder_add_message_file_uid(folder, fd, NULL); } int mailmh_folder_remove_message(struct mailmh_folder * folder, uint32_t index) { char * filename; struct mailmh_msg_info * msg_info; int res; int r; chashdatum key; chashdatum data; #if 0 r = mailmh_folder_update(folder); if (r != MAILMH_NO_ERROR) { res = r; goto err; } #endif r = mailmh_folder_get_message_filename(folder, index, &filename); if (filename == NULL) { res = r; goto err; } if (unlink(filename) == -1) { res = MAILMH_ERROR_FILE; goto free; } key.data = &index; key.len = sizeof(index); r = chash_get(folder->fl_msgs_hash, &key, &data); #if 0 msg_info = cinthash_find(folder->fl_msgs_hash, index); #endif if (r == 0) { msg_info = data.data; carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); #if 0 cinthash_remove(folder->fl_msgs_hash, index); #endif chash_delete(folder->fl_msgs_hash, &key, NULL); } return MAILMH_NO_ERROR; free: free(filename); err: return res; } int mailmh_folder_move_message(struct mailmh_folder * dest_folder, struct mailmh_folder * src_folder, uint32_t index) { int fd; char * filename; int r; #if 0 r = mailmh_folder_update(dest_folder); if (r != MAILMH_NO_ERROR) return r; r = mailmh_folder_update(src_folder); if (r != MAILMH_NO_ERROR) return r; #endif /* move on the same filesystem */ r = mailmh_folder_get_message_filename(src_folder, index, &filename); if (r != MAILMH_NO_ERROR) return r; r = mailmh_folder_alloc_msg(dest_folder, filename, &index); free(filename); if (r == MAILMH_NO_ERROR) return MAILMH_NO_ERROR; /* move on the different filesystems */ r = mailmh_folder_get_message_fd(src_folder, index, O_RDONLY, &fd); if (r != MAILMH_NO_ERROR) return r; r = mailmh_folder_add_message_file(dest_folder, fd); if (r != MAILMH_NO_ERROR) { close(fd); return r; } close(fd); r = mailmh_folder_remove_message(src_folder, index); return MAILMH_NO_ERROR; } unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder) { unsigned int i; unsigned int count; count = 0; for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) if (carray_get(folder->fl_msgs_tab, i) != NULL) count ++; return count; } |