From: Timo Sirainen Date: Mon, 17 Oct 2016 07:59:34 +0000 (+0300) Subject: lib-fs: Added FS_METADATA_WRITE_FNAME to allow renaming a file being written. X-Git-Tag: 2.2.26~121 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a8dca04dbcd7c415f53f266bdb8dc13532024a67;p=thirdparty%2Fdovecot%2Fcore.git lib-fs: Added FS_METADATA_WRITE_FNAME to allow renaming a file being written. --- diff --git a/src/lib-fs/fs-api.h b/src/lib-fs/fs-api.h index c1e7b3f699..4fd3cce780 100644 --- a/src/lib-fs/fs-api.h +++ b/src/lib-fs/fs-api.h @@ -13,6 +13,10 @@ struct hash_method; 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, diff --git a/src/lib-fs/fs-dict.c b/src/lib-fs/fs-dict.c index 8ee4cda389..aeff4c509b 100644 --- a/src/lib-fs/fs-dict.c +++ b/src/lib-fs/fs-dict.c @@ -185,6 +185,20 @@ static void fs_dict_write_stream(struct fs_file *_file) 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 @@ static int fs_dict_write_stream_finish(struct fs_file *_file, bool success) 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 @@ const struct fs fs_class_dict = { NULL, NULL, NULL, NULL, - NULL, NULL, + fs_default_set_metadata, + NULL, fs_dict_prefetch, NULL, fs_dict_read_stream, diff --git a/src/lib-fs/fs-posix.c b/src/lib-fs/fs-posix.c index 627ec319f5..c3984fa55b 100644 --- a/src/lib-fs/fs-posix.c +++ b/src/lib-fs/fs-posix.c @@ -443,6 +443,23 @@ fs_posix_read_stream(struct fs_file *_file, size_t max_buffer_size) 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 @@ static int fs_posix_write_finish(struct posix_fs_file *file) } } + 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 @@ const struct fs fs_class_posix = { fs_posix_file_close, NULL, NULL, NULL, - NULL, NULL, + fs_default_set_metadata, + NULL, fs_posix_prefetch, fs_posix_read, fs_posix_read_stream,