]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-fs: Added FS_METADATA_WRITE_FNAME to allow renaming a file being written.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 17 Oct 2016 07:59:34 +0000 (10:59 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 17 Oct 2016 20:11:21 +0000 (23:11 +0300)
src/lib-fs/fs-api.h
src/lib-fs/fs-dict.c
src/lib-fs/fs-posix.c

index c1e7b3f6994a02e26c8fb8eb362f257e156069ef..4fd3cce780daa9ec625a92210d642ae1e5a338b0 100644 (file)
@@ -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,
index 8ee4cda389d826c71700aaa2c5e4c8f62ee37fe0..aeff4c509b655383b2842f28f2753432f6742c46 100644 (file)
@@ -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,
index 627ec319f580e03209d1e834a5c85f356b29c444..c3984fa55b76b3dfebf6c72a69b0ee7a53e0611c 100644 (file)
@@ -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,