Mercurial > dovecot > core-2.2
changeset 15557:3c6a13c0d525
dict-file: Automatically mkdir missing parent directories if they don't exist.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 13 Dec 2012 12:14:57 +0200 |
parents | c0ad6afa4128 |
children | 4ec13ce76f6e |
files | src/lib-dict/dict-file.c |
diffstat | 1 files changed, 39 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-dict/dict-file.c Thu Dec 13 12:14:03 2012 +0200 +++ b/src/lib-dict/dict-file.c Thu Dec 13 12:14:57 2012 +0200 @@ -3,6 +3,7 @@ #include "lib.h" #include "array.h" #include "hash.h" +#include "mkdir-parents.h" #include "file-lock.h" #include "file-dotlock.h" #include "nfs-workarounds.h" @@ -424,6 +425,33 @@ return fd_copy_stat_permissions(&src_st, dest_fd, dest_path); } +static int file_dict_mkdir(struct file_dict *dict) +{ + const char *path, *p, *root; + struct stat st; + mode_t mode = 0700; + + p = strrchr(dict->path, '/'); + if (p == NULL) + return 0; + path = t_strdup_until(dict->path, p); + + if (stat_first_parent(path, &root, &st) < 0) { + i_error("stat(%s) failed: %m", root); + return -1; + } + if ((st.st_mode & S_ISGID) != 0) { + /* preserve parent's permissions when it has setgid bit */ + mode = st.st_mode; + } + + if (mkdir_parents(path, mode) < 0) { + i_error("mkdir_parents(%s) failed: %m", path); + return -1; + } + return 0; +} + static int file_dict_lock(struct file_dict *dict, struct file_lock **lock_r) { @@ -435,6 +463,11 @@ if (dict->fd == -1) { /* quota file doesn't exist yet, we need to create it */ dict->fd = open(dict->path, O_CREAT | O_RDWR, 0600); + if (dict->fd == -1 && errno == ENOENT) { + if (file_dict_mkdir(dict) < 0) + return -1; + dict->fd = open(dict->path, O_CREAT | O_RDWR, 0600); + } if (dict->fd == -1) { i_error("creat(%s) failed: %m", dict->path); return -1; @@ -485,6 +518,12 @@ case FILE_LOCK_METHOD_DOTLOCK: fd = file_dotlock_open(&file_dict_dotlock_settings, dict->path, 0, &dotlock); + if (fd == -1 && errno == ENOENT) { + if (file_dict_mkdir(dict) < 0) + return -1; + fd = file_dotlock_open(&file_dict_dotlock_settings, + dict->path, 0, &dotlock); + } if (fd == -1) { i_error("file dict commit: file_dotlock_open(%s) failed: %m", dict->path);