]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dict-file: When replacing the dict file, preserve its permissions.
authorTimo Sirainen <tss@iki.fi>
Fri, 1 May 2009 00:22:59 +0000 (20:22 -0400)
committerTimo Sirainen <tss@iki.fi>
Fri, 1 May 2009 00:22:59 +0000 (20:22 -0400)
--HG--
branch : HEAD

src/lib-dict/dict-file.c

index 60d7c2f9a292678a8046f70f1130541ece38c6e9..6ba82b75c12654df6dc2fb087eae93c46be19242 100644 (file)
@@ -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);