tcsh/tcsh-6.19.00-history-file-locking-order.patch

86 lines
2.5 KiB
Diff
Raw Normal View History

---
sh.c | 57 +++++++++++++++++++++++++++++++++------------------------
1 file changed, 33 insertions(+), 24 deletions(-)
--- sh.c
+++ sh.c 2016-11-25 08:05:00.501610199 +0000
@@ -1540,18 +1540,18 @@ int
#endif /*WINNT_NATIVE*/
srcfile(const char *f, int onlyown, int flg, Char **av)
{
- int *unit;
+ int unit, *hd = NULL;
- unit = xmalloc(sizeof(*unit));
- cleanup_push(unit, xfree);
- *unit = xopen(f, O_LARGEFILE |
+ unit = xopen(f, O_LARGEFILE |
((flg & HIST_FILE_WRLCK) ? (O_CREAT|O_RDWR) : O_RDONLY), 0600);
- if (*unit == -1)
+ if (unit < 0)
return 0; /* Error. */
- cleanup_push(unit, open_cleanup);
- *unit = dmove(*unit, -1);
- (void) close_on_exec(*unit, 1);
+ cleanup_push(&unit, open_cleanup);
+ unit = dmove(unit, -1);
+ cleanup_ignore(&unit);
+ cleanup_until(&unit);
+ (void) close_on_exec(unit, 1);
if (flg & (HIST_FILE_WRLCK | HIST_FILE_RDLCK)) {
struct flock fl;
@@ -1561,26 +1561,35 @@ srcfile(const char *f, int onlyown, int
fl.l_start = 0;
fl.l_len = 0;
- cleanup_push(unit, fcntl_cleanup);
- if (fcntl(*unit, F_SETLKW, &fl) == -1)
- cleanup_ignore(unit);
- }
+ hd = xmalloc(sizeof(*hd));
+ cleanup_push(hd, xfree);
- srcunit(*unit, onlyown, flg, av);
+ *hd = fcntl(unit, F_DUPFD_CLOEXEC, FSAFE+1);
+ cleanup_push(hd, open_cleanup);
- /* Unlock the unit, if we don't want to leave it locked (or open). */
- if ((flg & (HIST_FILE_WRLCK | HIST_FILE_RDLCK)) &&
- (!(flg & HIST_FILE_LOCK) || !(flg & HIST_FILE_OPEN)))
- cleanup_until(unit); /* fcntl_cleanup */
-
- /* Close the unit, if we don't want to leave it open. */
- if (!(flg & HIST_FILE_OPEN)) {
- cleanup_until(unit); /* open_cleanup */
- cleanup_until(unit); /* xfree */
- return -1; /* Not error but invalid file descriptor. */
+ fcntl(*hd, F_SETLKW, &fl);
+ cleanup_push(hd, fcntl_cleanup);
}
- return *unit; /* File descriptor (fd > FSAFE). */
+ cleanup_push(&unit, open_cleanup);
+ /*
+ * This one *does* do a cleanup_until() hence a open_cleanup()
+ * therefore use a duplicated fd to lock/unlock the history file
+ */
+ srcunit(unit, onlyown, flg, av);
+ cleanup_until(&unit); /* Close the official unit. */
+
+ if (!hd)
+ return -1; /* Not error but invalid file descriptor. */
+
+ if ((flg & HIST_FILE_OPEN) && (flg & HIST_FILE_LOCK))
+ return -1;
+
+ cleanup_until(hd); /* fcntl_cleanup */
+ cleanup_until(hd); /* open_cleanup */
+ cleanup_until(hd); /* xfree */
+
+ return unit; /* File descriptor (fd > FSAFE). */
}