changeset 20880:59a3ab804bcc

lib-fs: Added FS_METADATA_WRITE_FNAME to allow renaming a file being written.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Mon, 17 Oct 2016 10:59:34 +0300
parents c9e32ef49048
children 95822083a88b
files src/lib-fs/fs-api.h src/lib-fs/fs-dict.c src/lib-fs/fs-posix.c
diffstat 3 files changed, 41 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-fs/fs-api.h	Tue Oct 11 01:04:39 2016 +0300
+++ b/src/lib-fs/fs-api.h	Mon Oct 17 10:59:34 2016 +0300
@@ -13,6 +13,10 @@
    This can be later on used to optimize reads by setting it before reading
    the file. */
 #define FS_METADATA_OBJECTID FS_METADATA_INTERNAL_PREFIX"ObjectID"
+/* Calling this before fs_write_stream_finish() allows renaming the filename.
+   This can be useful if you don't know the final filename before writing it
+   (e.g. filename contains the file size). */
+#define FS_METADATA_WRITE_FNAME FS_METADATA_INTERNAL_PREFIX"WriteFilename"
 
 enum fs_properties {
 	FS_PROPERTY_METADATA	= 0x01,
--- a/src/lib-fs/fs-dict.c	Tue Oct 11 01:04:39 2016 +0300
+++ b/src/lib-fs/fs-dict.c	Mon Oct 17 10:59:34 2016 +0300
@@ -185,6 +185,20 @@
 	o_stream_set_name(_file->output, file->key);
 }
 
+static void fs_dict_write_rename_if_needed(struct dict_fs_file *file)
+{
+	struct dict_fs *fs = (struct dict_fs *)file->file.fs;
+	const char *new_fname;
+
+	new_fname = fs_metadata_find(&file->file.metadata, FS_METADATA_WRITE_FNAME);
+	if (new_fname == NULL)
+		return;
+
+	file->file.path = p_strdup(file->pool, new_fname);
+	file->key = fs->path_prefix == NULL ? p_strdup(file->pool, new_fname) :
+		p_strconcat(file->pool, fs->path_prefix, new_fname, NULL);
+}
+
 static int fs_dict_write_stream_finish(struct fs_file *_file, bool success)
 {
 	struct dict_fs_file *file = (struct dict_fs_file *)_file;
@@ -195,6 +209,7 @@
 	if (!success)
 		return -1;
 
+	fs_dict_write_rename_if_needed(file);
 	trans = dict_transaction_begin(fs->dict);
 	switch (fs->encoding) {
 	case FS_DICT_VALUE_ENCODING_RAW:
@@ -302,7 +317,8 @@
 		NULL,
 		NULL,
 		NULL, NULL,
-		NULL, NULL,
+		fs_default_set_metadata,
+		NULL,
 		fs_dict_prefetch,
 		NULL,
 		fs_dict_read_stream,
--- a/src/lib-fs/fs-posix.c	Tue Oct 11 01:04:39 2016 +0300
+++ b/src/lib-fs/fs-posix.c	Mon Oct 17 10:59:34 2016 +0300
@@ -443,6 +443,23 @@
 	return input;
 }
 
+static void fs_posix_write_rename_if_needed(struct posix_fs_file *file)
+{
+	struct posix_fs *fs = (struct posix_fs *)file->file.fs;
+	const char *new_fname;
+
+	new_fname = fs_metadata_find(&file->file.metadata, FS_METADATA_WRITE_FNAME);
+	if (new_fname == NULL)
+		return;
+
+	i_free(file->file.path);
+	file->file.path = i_strdup(new_fname);
+
+	i_free(file->full_path);
+	file->full_path = fs->path_prefix == NULL ? i_strdup(new_fname) :
+		i_strconcat(fs->path_prefix, new_fname, NULL);
+}
+
 static int fs_posix_write_finish(struct posix_fs_file *file)
 {
 	int ret, old_errno;
@@ -455,6 +472,7 @@
 		}
 	}
 
+	fs_posix_write_rename_if_needed(file);
 	switch (file->open_mode) {
 	case FS_OPEN_MODE_CREATE_UNIQUE_128:
 	case FS_OPEN_MODE_CREATE:
@@ -872,7 +890,8 @@
 		fs_posix_file_close,
 		NULL,
 		NULL, NULL,
-		NULL, NULL,
+		fs_default_set_metadata,
+		NULL,
 		fs_posix_prefetch,
 		fs_posix_read,
 		fs_posix_read_stream,