From: Timo Sirainen Date: Fri, 1 May 2009 00:22:59 +0000 (-0400) Subject: dict-file: When replacing the dict file, preserve its permissions. X-Git-Tag: 2.0.alpha1~862 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b141c303bf09b6ae43e1eb4aac1e1a6b796b9d35;p=thirdparty%2Fdovecot%2Fcore.git dict-file: When replacing the dict file, preserve its permissions. --HG-- branch : HEAD --- diff --git a/src/lib-dict/dict-file.c b/src/lib-dict/dict-file.c index 60d7c2f9a2..6ba82b75c1 100644 --- a/src/lib-dict/dict-file.c +++ b/src/lib-dict/dict-file.c @@ -280,6 +280,38 @@ static void file_dict_apply_changes(struct file_dict_transaction_context *ctx) } } +static int fd_copy_permissions(int src_fd, const char *src_path, + int dest_fd, const char *dest_path) +{ + struct stat src_st, dest_st; + + if (fstat(src_fd, &src_st) < 0) { + i_error("fstat(%s) failed: %m", src_path); + return -1; + } + if (fstat(dest_fd, &dest_st) < 0) { + i_error("fstat(%s) failed: %m", dest_path); + return -1; + } + + if (src_st.st_gid != dest_st.st_gid) { + if (fchown(dest_fd, (uid_t)-1, src_st.st_gid) < 0) { + i_error("fchown(%s, -1, %s) failed: %m", + dest_path, dec2str(src_st.st_gid)); + return -1; + } + } + + if ((src_st.st_mode & 07777) != (dest_st.st_mode & 07777)) { + if (fchmod(dest_fd, src_st.st_mode & 07777) < 0) { + i_error("fchmod(%s, %o) failed: %m", + dest_path, (int)(src_st.st_mode & 0777)); + return -1; + } + } + return 0; +} + static int file_dict_write_changes(struct file_dict_transaction_context *ctx) { struct file_dict *dict = (struct file_dict *)ctx->ctx.dict; @@ -301,6 +333,11 @@ static int file_dict_write_changes(struct file_dict_transaction_context *ctx) file_dotlock_delete(&dotlock); return -1; } + if (dict->fd != -1) { + /* preserve the permissions */ + (void)fd_copy_permissions(dict->fd, dict->path, fd, + file_dotlock_get_lock_path(dotlock)); + } file_dict_apply_changes(ctx); output = o_stream_create_fd(fd, 0, FALSE);