about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWayne Davison <wayned@users.sourceforge.net>2005-12-17 07:58:12 +0000
committerWayne Davison <wayned@users.sourceforge.net>2005-12-17 07:58:12 +0000
commit78168105def44c786da0291aff0706fbd339fa40 (patch)
tree632741cbd4f74f0d291aa2025c1c28e5f3d9e54d
parentf7037211ad3a9e4f61a5d1aad8eceab5e01b4663 (diff)
downloadzsh-78168105def44c786da0291aff0706fbd339fa40.tar.gz
zsh-78168105def44c786da0291aff0706fbd339fa40.tar.xz
zsh-78168105def44c786da0291aff0706fbd339fa40.zip
Two changes in the HIST_SAVE_BY_COPY code: (1) preserve the group
and permissions on the history file, and (2) fail if zsh's euid
differs from the file's uid (since that would change the history
file's owner).
-rw-r--r--Src/hist.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/Src/hist.c b/Src/hist.c
index 90e97313e..1a9140801 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -2080,8 +2080,26 @@ savehistfile(char *fn, int err, int writeflags)
 	tmpfile = bicat(unmeta(fn), ".new");
 	if (unlink(tmpfile) < 0 && errno != ENOENT)
 	    out = NULL;
-	else
-	    out = fdopen(open(tmpfile, O_CREAT | O_WRONLY | O_EXCL, 0600), "w");
+	else {
+	    struct stat sb;
+	    int old_exists = stat(unmeta(fn), &sb) == 0;
+
+	    if (old_exists && sb.st_uid != geteuid()) {
+		free(tmpfile);
+		tmpfile = NULL; /* Avoid an error about HISTFILE.new */
+		out = NULL;
+	    } else
+		out = fdopen(open(tmpfile, O_CREAT | O_WRONLY | O_EXCL, 0600), "w");
+
+#ifdef HAVE_FCHMOD
+	    if (old_exists && out) {
+#ifdef HAVE_FCHOWN
+		fchown(fileno(out), sb.st_uid, sb.st_gid);
+#endif
+		fchmod(fileno(out), sb.st_mode);
+	    }
+#endif
+	}
     }
     if (out) {
 	for (; he && he->histnum <= xcurhist; he = down_histent(he)) {