changeset 9000:b02c642b4e51 HEAD

dict-file: When replacing the dict file, preserve its permissions.
author Timo Sirainen <tss@iki.fi>
date Thu, 30 Apr 2009 20:22:49 -0400
parents afc1b0ef120d
children 5302ce189a70
files src/lib-dict/dict-file.c
diffstat 1 files changed, 37 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-dict/dict-file.c	Thu Apr 30 20:00:09 2009 -0400
+++ b/src/lib-dict/dict-file.c	Thu Apr 30 20:22:49 2009 -0400
@@ -280,6 +280,38 @@
 	}
 }
 
+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 @@
 		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);