1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-10-27 04:40:59 +01:00

24818: add HIST_FCNTL_LOCK.

unposted: update NEWS with new features
This commit is contained in:
Peter Stephenson 2008-04-17 10:23:45 +00:00
parent 35cedab218
commit 78ce07b49f
7 changed files with 141 additions and 6 deletions

View file

@ -2021,6 +2021,20 @@ readhistfile(char *fn, int err, int readflags)
else if (!lockhistfile(fn, 1))
return;
if ((in = fopen(unmeta(fn), "r"))) {
#ifdef HAVE_FCNTL_H
if (isset(HISTFCNTLLOCK)) {
struct flock lck;
lck.l_type = F_RDLCK;
lck.l_whence = SEEK_SET;
lck.l_start = 0;
lck.l_len = 0; /* lock the whole file */
if (fcntl(fileno(in), F_SETLKW, &lck) == -1) {
fclose(in);
return;
}
}
#endif
nwordlist = 64;
wordlist = (short *)zalloc(nwordlist*sizeof(short));
bufsiz = 1024;
@ -2149,6 +2163,68 @@ readhistfile(char *fn, int err, int readflags)
unlockhistfile(fn);
}
#ifdef HAVE_FCNTL_H
/**/
static int
wlockfile(int fd)
{
struct flock lck;
int ctr = 8;
lck.l_type = F_WRLCK;
lck.l_whence = SEEK_SET;
lck.l_start = 0;
lck.l_len = 0;
while (fcntl(fd, F_SETLKW, &lck) == -1) {
if (--ctr < 0)
return 1;
sleep (1);
}
return 0;
}
#endif
/**/
static int
safe_unlink(const char *pathname)
{
#ifdef HAVE_FCNTL_H
if (isset(HISTFCNTLLOCK)) {
int fd = open(pathname, O_WRONLY | O_NOCTTY, 0600);
if (fd >= 0) {
int err = wlockfile(fd) || unlink(pathname);
close(fd);
return err;
} else {
return errno != ENOENT;
}
}
#endif
return unlink(pathname) && errno != ENOENT;
}
/**/
static int
safe_rename(const char *oldpath, const char *newpath)
{
#ifdef HAVE_FCNTL_H
if (isset(HISTFCNTLLOCK)) {
int fd = open(newpath, O_CREAT | O_WRONLY | O_NOCTTY, 0600);
if (fd < 0) {
return 1;
} else if (wlockfile(fd)) {
close(fd);
return 1;
} else {
int err = rename(oldpath, newpath);
close(fd);
return err;
}
}
#endif
return rename(oldpath, newpath);
}
/**/
void
savehistfile(char *fn, int err, int writeflags)
@ -2158,6 +2234,9 @@ savehistfile(char *fn, int err, int writeflags)
Histent he;
zlong xcurhist = curhist - !!(histactive & HA_ACTIVE);
int extended_history = isset(EXTENDEDHISTORY);
#ifdef HAVE_FTRUNCATE
int truncate_history = 0;
#endif
int ret;
if (!interact || savehistsiz <= 0 || !hist_ring
@ -2196,12 +2275,16 @@ savehistfile(char *fn, int err, int writeflags)
tmpfile = NULL;
out = fd >= 0 ? fdopen(fd, "a") : NULL;
} else if (!isset(HISTSAVEBYCOPY)) {
int fd = open(unmeta(fn), O_CREAT | O_WRONLY | O_TRUNC | O_NOCTTY, 0600);
int fd = open(unmeta(fn), O_CREAT | O_WRONLY | O_NOCTTY, 0600);
tmpfile = NULL;
out = fd >= 0 ? fdopen(fd, "w") : NULL;
#ifdef HAVE_FTRUNCATE
/* The file should be truncated after its locking. */
truncate_history = 1;
#endif
} else {
tmpfile = bicat(unmeta(fn), ".new");
if (unlink(tmpfile) < 0 && errno != ENOENT)
if (safe_unlink(tmpfile))
out = NULL;
else {
struct stat sb;
@ -2239,7 +2322,18 @@ savehistfile(char *fn, int err, int writeflags)
#endif
}
}
#ifdef HAVE_FCNTL_H
if (out && isset(HISTFCNTLLOCK) && wlockfile(fileno(out))) {
zerr("can't lock file (timeout) -- history %s not updated", fn);
err = 0; /* Don't report a generic error below. */
out = NULL;
}
#endif
if (out) {
#ifdef HAVE_FTRUNCATE
if (truncate_history)
ftruncate(fileno(out), 0);
#endif
ret = 0;
for (; he && he->histnum <= xcurhist; he = down_histent(he)) {
if ((writeflags & HFILE_SKIPDUPS && he->node.flags & HIST_DUP)
@ -2285,16 +2379,19 @@ savehistfile(char *fn, int err, int writeflags)
zsfree(lasthist.text);
lasthist.text = ztrdup(start);
}
}
if (fclose(out) < 0 && ret >= 0)
} else if (ret >= 0 && fflush(out) < 0) {
ret = -1;
}
if (ret >= 0) {
if (tmpfile) {
if (rename(tmpfile, unmeta(fn)) < 0)
/* out has been flushed and the file must be renamed while
being open so that the lock is still valid */
if (safe_rename(tmpfile, unmeta(fn)))
zerr("can't rename %s.new to $HISTFILE", fn);
free(tmpfile);
tmpfile = NULL;
}
fclose(out);
if (writeflags & HFILE_SKIPOLD
&& !(writeflags & (HFILE_FAST | HFILE_NO_REWRITE))) {
@ -2314,6 +2411,8 @@ savehistfile(char *fn, int err, int writeflags)
pophiststack();
histactive = remember_histactive;
}
} else {
fclose(out);
}
} else
ret = -1;

View file

@ -135,6 +135,7 @@ static struct optname optns[] = {
{{NULL, "histallowclobber", 0}, HISTALLOWCLOBBER},
{{NULL, "histbeep", OPT_ALL}, HISTBEEP},
{{NULL, "histexpiredupsfirst",0}, HISTEXPIREDUPSFIRST},
{{NULL, "histfcntllock", 0}, HISTFCNTLLOCK},
{{NULL, "histfindnodups", 0}, HISTFINDNODUPS},
{{NULL, "histignorealldups", 0}, HISTIGNOREALLDUPS},
{{NULL, "histignoredups", 0}, HISTIGNOREDUPS},

View file

@ -1749,6 +1749,7 @@ enum {
HISTALLOWCLOBBER,
HISTBEEP,
HISTEXPIREDUPSFIRST,
HISTFCNTLLOCK,
HISTFINDNODUPS,
HISTIGNOREALLDUPS,
HISTIGNOREDUPS,