diff options
author | Wayne Davison <wayned@users.sourceforge.net> | 2005-12-17 07:58:12 +0000 |
---|---|---|
committer | Wayne Davison <wayned@users.sourceforge.net> | 2005-12-17 07:58:12 +0000 |
commit | 78168105def44c786da0291aff0706fbd339fa40 (patch) | |
tree | 632741cbd4f74f0d291aa2025c1c28e5f3d9e54d | |
parent | f7037211ad3a9e4f61a5d1aad8eceab5e01b4663 (diff) | |
download | zsh-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.c | 22 |
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)) { |