[dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-copy.c, 1.44, 1.45 maildir-mail.c, 1.23, 1.24 maildir-save.c, 1.71, 1.72 maildir-storage.h, 1.50, 1.51 maildir-util.c, 1.14, 1.15

cras at dovecot.org cras at dovecot.org
Fri Jun 16 12:40:43 EEST 2006


Update of /var/lib/cvs/dovecot/src/lib-storage/index/maildir
In directory talvi:/tmp/cvs-serv30783/lib-storage/index/maildir

Modified Files:
	maildir-copy.c maildir-mail.c maildir-save.c maildir-storage.h 
	maildir-util.c 
Log Message:
Add ",S=size" to maildir filenames when quota plugin is loaded with
Maildir++ backend.



Index: maildir-copy.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-copy.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- maildir-copy.c	9 May 2006 11:57:38 -0000	1.44
+++ maildir-copy.c	16 Jun 2006 09:40:40 -0000	1.45
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "array.h"
 #include "ioloop.h"
+#include "str.h"
 #include "maildir-storage.h"
 #include "maildir-uidlist.h"
 #include "maildir-keywords.h"
@@ -11,18 +12,59 @@
 
 #include <stdlib.h>
 #include <unistd.h>
+#include <sys/stat.h>
 
 struct hardlink_ctx {
-	const char *dest_path;
-	bool success;
+	string_t *dest_path;
+	const char *dest_fname;
+	unsigned int base_end_pos;
+
+	unsigned int size_set:1;
+	unsigned int success:1;
 };
 
+static int do_save_mail_size(struct maildir_mailbox *mbox, const char *path,
+			     struct hardlink_ctx *ctx)
+{
+	const char *fname, *str;
+	struct stat st;
+	uoff_t size;
+
+	fname = strrchr(path, '/');
+	fname = fname != NULL ? fname + 1 : path;
+
+	if (!maildir_filename_get_size(fname, MAILDIR_EXTRA_FILE_SIZE,
+				       &size)) {
+		if (stat(path, &st) < 0) {
+			if (errno == ENOENT)
+				return 0;
+			mail_storage_set_critical(STORAGE(mbox->storage),
+						  "stat(%s) failed: %m", path);
+			return -1;
+		}
+		size = st.st_size;
+	}
+
+	str = t_strdup_printf(",S=%"PRIuUOFF_T, size);
+	str_insert(ctx->dest_path, ctx->base_end_pos, str);
+
+	ctx->dest_fname = strrchr(str_c(ctx->dest_path), '/') + 1;
+	ctx->size_set = TRUE;
+	return 1;
+}
+
 static int do_hardlink(struct maildir_mailbox *mbox, const char *path,
 		       void *context)
 {
 	struct hardlink_ctx *ctx = context;
+	int ret;
 
-	if (link(path, ctx->dest_path) < 0) {
+	if (mbox->storage->save_size_in_filename && !ctx->size_set) {
+		if ((ret = do_save_mail_size(mbox, path, ctx)) <= 0)
+			return ret;
+	}
+
+	if (link(path, str_c(ctx->dest_path)) < 0) {
 		if (errno == ENOENT)
 			return 0;
 
@@ -36,7 +78,7 @@
 
 		mail_storage_set_critical(STORAGE(mbox->storage),
 					  "link(%s, %s) failed: %m",
-					  path, ctx->dest_path);
+					  path, str_c(ctx->dest_path));
 		return -1;
 	}
 
@@ -55,7 +97,6 @@
 		(struct maildir_mailbox *)mail->box;
 	struct maildir_save_context *ctx;
 	struct hardlink_ctx do_ctx;
-	const char *dest_fname;
 	uint32_t seq;
 
 	i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
@@ -70,31 +111,33 @@
 		flags |= MAIL_RECENT;
 
 	memset(&do_ctx, 0, sizeof(do_ctx));
+	do_ctx.dest_path = str_new(default_pool, 512);
 
 	/* the generated filename is _always_ unique, so we don't bother
 	   trying to check if it already exists */
-	dest_fname = maildir_generate_tmp_filename(&ioloop_timeval);
+	do_ctx.dest_fname = maildir_generate_tmp_filename(&ioloop_timeval);
 	if (keywords == NULL || keywords->count == 0) {
 		/* no keywords, hardlink directly to destination */
 		if (flags == MAIL_RECENT) {
-			do_ctx.dest_path =
-				t_strconcat(dest_mbox->path, "/new/",
-					    dest_fname, NULL);
+			str_printfa(do_ctx.dest_path, "%s/new/%s",
+				    dest_mbox->path, do_ctx.dest_fname);
+			do_ctx.base_end_pos = str_len(do_ctx.dest_path);
 		} else {
-			const char *fname;
-
-			fname = maildir_filename_set_flags(NULL, dest_fname,
-							   flags, NULL);
-
-			do_ctx.dest_path =
-				t_strconcat(dest_mbox->path, "/cur/",
-					    fname, NULL);
+			str_printfa(do_ctx.dest_path, "%s/cur/",
+				    dest_mbox->path);
+			do_ctx.base_end_pos = str_len(do_ctx.dest_path) +
+				strlen(do_ctx.dest_fname);
+			str_append(do_ctx.dest_path,
+				   maildir_filename_set_flags(NULL,
+							      do_ctx.dest_fname,
+							      flags, NULL));
 		}
 	} else {
 		/* keywords, hardlink to tmp/ with basename and later when we
 		   have uidlist locked, move it to new/cur. */
-		do_ctx.dest_path =
-			t_strconcat(dest_mbox->path, "/tmp/", dest_fname, NULL);
+		str_printfa(do_ctx.dest_path, "%s/tmp/%s",
+			    dest_mbox->path, do_ctx.dest_fname);
+		do_ctx.base_end_pos = str_len(do_ctx.dest_path);
 	}
 	if (maildir_file_do(src_mbox, mail->uid, do_hardlink, &do_ctx) < 0)
 		return -1;
@@ -106,12 +149,12 @@
 
 	if (keywords == NULL || keywords->count == 0) {
 		/* hardlinked to destination, set hardlinked-flag */
-		seq = maildir_save_add(t, dest_fname,
+		seq = maildir_save_add(t, do_ctx.dest_fname,
 				       flags | MAILDIR_SAVE_FLAG_HARDLINK, NULL,
 				       dest_mail);
 	} else {
 		/* hardlinked to tmp/, treat as normal copied mail */
-		seq = maildir_save_add(t, dest_fname, flags, keywords,
+		seq = maildir_save_add(t, do_ctx.dest_fname, flags, keywords,
 				       dest_mail);
 	}
 	return 1;

Index: maildir-mail.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-mail.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- maildir-mail.c	16 May 2006 09:10:33 -0000	1.23
+++ maildir-mail.c	16 Jun 2006 09:40:40 -0000	1.24
@@ -121,7 +121,7 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
 	struct index_mail_data *data = &mail->data;
-	const char *fname, *p;
+	const char *fname;
 	uoff_t virtual_size;
         enum maildir_uidlist_rec_flag flags;
 
@@ -145,22 +145,11 @@
 	}
 
 	/* size can be included in filename */
-	p = strstr(fname, MAILDIR_EXTRA_SEP_S MAILDIR_EXTRA_VIRTUAL_SIZE "=");
-	if (p != NULL) {
-		p += 3;
-		virtual_size = 0;
-		while (*p >= '0' && *p <= '9') {
-			virtual_size = virtual_size * 10 + (*p - '0');
-			p++;
-		}
-
-		if (*p == MAILDIR_INFO_SEP || *p == MAILDIR_EXTRA_SEP ||
-		    *p == '\0') {
-			index_mail_cache_add(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE,
-					     &virtual_size,
-					     sizeof(virtual_size));
-			return virtual_size;
-		}
+	if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
+				      &virtual_size)) {
+		index_mail_cache_add(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE,
+				     &virtual_size, sizeof(virtual_size));
+		return virtual_size;
 	}
 
 	return index_mail_get_virtual_size(_mail);
@@ -195,7 +184,7 @@
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
 	struct index_mail_data *data = &mail->data;
 	struct stat st;
-	const char *fname, *p;
+	const char *fname;
 	uoff_t size;
 	enum maildir_uidlist_rec_flag flags;
 
@@ -214,26 +203,13 @@
 	}
 
 	/* size can be included in filename */
-	p = strstr(fname, MAILDIR_EXTRA_SEP_S MAILDIR_EXTRA_FILE_SIZE "=");
-	if (p != NULL) {
-		p += 3;
-		size = 0;
-		while (*p >= '0' && *p <= '9') {
-			size = size * 10 + (*p - '0');
-			p++;
-		}
-
-		if (*p != MAILDIR_INFO_SEP &&
-		    *p != MAILDIR_EXTRA_SEP && *p != '\0')
-			size = (uoff_t)-1;
-	}
-
-	if (size == (uoff_t)-1) {
+	if (!maildir_filename_get_size(fname, MAILDIR_EXTRA_FILE_SIZE, &size)) {
 		if (_mail->uid != 0) {
 			if (maildir_file_do(mbox, _mail->uid,
 					    do_stat, &st) <= 0)
 				return (uoff_t)-1;
 		} else {
+			/* saved mail which hasn't been committed yet */
 			if (do_stat(mbox, fname, &st) <= 0)
 				return (uoff_t)-1;
 		}

Index: maildir-save.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-save.c,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -d -r1.71 -r1.72
--- maildir-save.c	9 May 2006 11:57:38 -0000	1.71
+++ maildir-save.c	16 Jun 2006 09:40:40 -0000	1.72
@@ -24,6 +24,7 @@
 	struct maildir_filename *next;
 	const char *basename;
 
+	uoff_t size;
 	enum mail_flags flags;
 	unsigned int keywords_count;
 	/* unsigned int keywords[]; */
@@ -58,7 +59,8 @@
 };
 
 static int maildir_file_move(struct maildir_save_context *ctx,
-			     const char *basename, const char *dest)
+			     const char *tmpname, const char *destname,
+			     bool newdir)
 {
 	const char *tmp_path, *new_path;
 	int ret;
@@ -69,10 +71,10 @@
 	   new/ directory can't have flags. alternative would be to write it
 	   in new/ and set the flags dirty in index file, but in that case
 	   external MUAs would see wrong flags. */
-	tmp_path = t_strconcat(ctx->tmpdir, "/", basename, NULL);
-	new_path = dest == NULL ?
-		t_strconcat(ctx->newdir, "/", basename, NULL) :
-		t_strconcat(ctx->curdir, "/", dest, NULL);
+	tmp_path = t_strconcat(ctx->tmpdir, "/", tmpname, NULL);
+	new_path = newdir ?
+		t_strconcat(ctx->newdir, "/", destname, NULL) :
+		t_strconcat(ctx->curdir, "/", destname, NULL);
 
 	if (link(tmp_path, new_path) == 0)
 		ret = 0;
@@ -148,6 +150,7 @@
 					      keywords->count));
 	mf->basename = p_strdup(ctx->pool, base_fname);
 	mf->flags = flags;
+	mf->size = (uoff_t)-1;
 
 	if (*ctx->files_tail != NULL)
 		(*ctx->files_tail)->next = mf;
@@ -204,24 +207,37 @@
 	return ctx->seq;
 }
 
-static const char *
+static bool
 maildir_get_updated_filename(struct maildir_save_context *ctx,
-			     struct maildir_filename *mf)
+			     struct maildir_filename *mf,
+			     const char **fname_r)
 {
+	const char *basename = mf->basename;
+
+	if (ctx->mbox->storage->save_size_in_filename &&
+	    mf->size != (uoff_t)-1) {
+		basename = t_strdup_printf("%s,S=%"PRIuUOFF_T,
+					   basename, mf->size);
+	}
+
 	if (mf->keywords_count == 0) {
-		if ((mf->flags & MAIL_FLAGS_MASK) == MAIL_RECENT)
-			return NULL;
-		return maildir_filename_set_flags(NULL, mf->basename,
-						  mf->flags & MAIL_FLAGS_MASK,
-						  NULL);
+		if ((mf->flags & MAIL_FLAGS_MASK) == MAIL_RECENT) {
+			*fname_r = basename;
+			return TRUE;
+		}
+
+		*fname_r = maildir_filename_set_flags(NULL, basename,
+					mf->flags & MAIL_FLAGS_MASK, NULL);
+		return FALSE;
 	}
 
 	buffer_update_const_data(ctx->keywords_buffer, mf + 1,
 				 mf->keywords_count * sizeof(unsigned int));
-	return maildir_filename_set_flags(
+	*fname_r = maildir_filename_set_flags(
 			maildir_sync_get_keywords_sync_ctx(ctx->sync_ctx),
-			mf->basename, mf->flags & MAIL_FLAGS_MASK,
+			basename, mf->flags & MAIL_FLAGS_MASK,
 			&ctx->keywords_array);
+	return FALSE;
 }
 
 static const char *maildir_mf_get_path(struct maildir_save_context *ctx,
@@ -235,8 +251,7 @@
 	}
 
 	/* already moved to new/ or cur/ */
-	fname = maildir_get_updated_filename(ctx, mf);
-	if (fname == NULL)
+	if (maildir_get_updated_filename(ctx, mf, &fname))
 		return t_strdup_printf("%s/%s", ctx->newdir, mf->basename);
 	else
 		return t_strdup_printf("%s/%s", ctx->curdir, fname);
@@ -359,6 +374,9 @@
 		return -1;
 	}
 
+	/* remember the size in case we want to add it to filename */
+	ctx->files->size = ctx->output->offset;
+
 	t_push();
 	path = t_strconcat(ctx->tmpdir, "/", ctx->files->basename, NULL);
 
@@ -447,7 +465,8 @@
 	struct maildir_filename *mf;
 	uint32_t first_uid, last_uid;
 	enum maildir_uidlist_rec_flag flags;
-	const char *dest, *fname;
+	const char *dest;
+	bool newdir;
 	int ret;
 
 	i_assert(ctx->output == NULL);
@@ -488,18 +507,19 @@
 	ctx->moving = TRUE;
 	for (mf = ctx->files; mf != NULL && ret == 0; mf = mf->next) {
 		t_push();
-		dest = maildir_get_updated_filename(ctx, mf);
-		fname = dest != NULL ? dest : mf->basename;
+		newdir = maildir_get_updated_filename(ctx, mf, &dest);
 
 		/* if hardlink-flag is set, the file is already in destination.
 		   if the hardlinked mail contained keywords, it was linked
 		   into tmp/ and it doesn't have the hardlink-flag set, so it's
 		   treated as any other saved mail. */
-		if ((mf->flags & MAILDIR_SAVE_FLAG_HARDLINK) == 0)
-			ret = maildir_file_move(ctx, mf->basename, dest);
+		if ((mf->flags & MAILDIR_SAVE_FLAG_HARDLINK) == 0) {
+			ret = maildir_file_move(ctx, mf->basename,
+						dest, newdir);
+		}
 		if (ret == 0) {
 			ret = maildir_uidlist_sync_next(ctx->uidlist_sync_ctx,
-							fname, flags);
+							dest, flags);
 			i_assert(ret != 0);
 			ret = ret < 0 ? -1 : 0;
 		}

Index: maildir-storage.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-storage.h,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- maildir-storage.h	9 May 2006 11:57:38 -0000	1.50
+++ maildir-storage.h	16 Jun 2006 09:40:40 -0000	1.51
@@ -27,10 +27,10 @@
 #define MAILDIR_MAX_KEYWORDS (MAILDIR_KEYWORD_LAST - MAILDIR_KEYWORD_FIRST + 1)
 
 /* Maildir++ extension: include file size in the filename to avoid stat() */
-#define MAILDIR_EXTRA_FILE_SIZE "S"
+#define MAILDIR_EXTRA_FILE_SIZE 'S'
 /* Something (can't remember what anymore) could use 'W' in filename to avoid
    calculating file's virtual size (added missing CRs). */
-#define MAILDIR_EXTRA_VIRTUAL_SIZE "W"
+#define MAILDIR_EXTRA_VIRTUAL_SIZE 'W'
 
 #define MAILDIR_SAVE_FLAG_HARDLINK 0x10000000
 #define MAILDIR_SAVE_FLAG_DELETED  0x20000000
@@ -53,6 +53,7 @@
 
 	const char *control_dir;
 	unsigned int copy_with_hardlinks:1;
+	unsigned int save_size_in_filename:1;
 };
 
 struct maildir_mailbox {
@@ -89,6 +90,7 @@
 const char *maildir_generate_tmp_filename(const struct timeval *tv);
 int maildir_create_tmp(struct maildir_mailbox *mbox, const char *dir,
 		       mode_t mode, const char **fname_r);
+bool maildir_filename_get_size(const char *fname, char type, uoff_t *size_r);
 
 struct mailbox_list_context *
 maildir_mailbox_list_init(struct mail_storage *storage,

Index: maildir-util.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-util.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- maildir-util.c	6 Mar 2006 18:15:37 -0000	1.14
+++ maildir-util.c	16 Jun 2006 09:40:40 -0000	1.15
@@ -134,6 +134,34 @@
 	return fd;
 }
 
+bool maildir_filename_get_size(const char *fname, char type, uoff_t *size_r)
+{
+	uoff_t size = 0;
+
+	for (; *fname != '\0'; fname++) {
+		if (*fname == ',' && fname[1] == type && fname[2] == '=') {
+			fname += 3;
+			break;
+		}
+	}
+
+	if (*fname == '\0')
+		return FALSE;
+
+	while (*fname >= '0' && *fname <= '9') {
+		size = size * 10 + (*fname - '0');
+		fname++;
+	}
+
+	if (*fname != MAILDIR_INFO_SEP &&
+	    *fname != MAILDIR_EXTRA_SEP &&
+	    *fname != '\0')
+		return FALSE;
+
+	*size_r = size;
+	return TRUE;
+}
+
 /* a char* hash function from ASU -- from glib */
 unsigned int maildir_hash(const void *p)
 {



More information about the dovecot-cvs mailing list