1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-05-19 14:36:04 +02: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

@ -1,3 +1,11 @@
2008-04-17 Peter Stephenson <pws@csr.com>
* unposted: NEWS: list new features so far since 4.3.6.
* Vincent Lefevre: 24818: Doc/Zsh/options.yo (modified),
Src/hist.c (with #ifdef HAVE_TRUNCATE), Src/options.c, Src/zsh.h:
history file locking using fcntl().
2008-04-16 Clint Adams <clint@zsh.org>
* 248??: Completion/Unix/Command/_git: some fixes and updates for

View File

@ -577,6 +577,15 @@ than tt(SAVEHIST) in order to give you some room for the duplicated
events, otherwise this option will behave just like
tt(HIST_IGNORE_ALL_DUPS) once the history fills up with unique events.
)
pindex(HIST_FCNTL_LOCK)
item(tt(HIST_FCNTL_LOCK))(
When writing out the history file, by default zsh uses ad-hoc file locking
to avoid known problems with locking on some operating systems. With this
option locking is done by means of the system's tt(fcntl) call, where
this method is available. On recent operating systems this may
provide better performance, in particular avoiding history corruption when
files are stored on NFS.
)
pindex(HIST_FIND_NO_DUPS)
cindex(history, ignoring duplicates in search)
item(tt(HIST_FIND_NO_DUPS))(

View File

@ -2046,7 +2046,8 @@ sect(How does zsh handle multibyte input and output?)
all terminals handle this, even if they correctly display the base
multibyte character, this option is not on by default. The KDE terminal
emulator tt(konsole), tt(rxvt-unicode), and the Unicode version of
xterm, tt(uxterm), are known to handle combining characters.
xterm, tt(xterm -u8) or the front-end tt(uxterm), are known to handle
combining characters.
The tt(COMBINING_CHARS) option only affects output; combining characters
may always be input, but when the option is off will be displayed

16
NEWS
View File

@ -4,6 +4,22 @@ CHANGES FROM PREVIOUS VERSIONS OF ZSH
Note also the list of incompatibilities in the README file.
Major changes between versions 4.3.6 and 4.3.7
----------------------------------------------
The option COMBINING_CHARS has been added. When it is set, the
line editor assumes the terminal is capable of displaying zero-width
combining characters (typically accents) correctly as modifications
to the base character, and will act accordingly.
The option HIST_FCNTL_LOCK has been added to provide locking of history
files using the system call fcntl(). On recent NFS implementations this
may provide better reliability.
Highlighting of sections of the command line is now supported, controlled
by the array parameter zle_highlight and the ZLE special parameter
REGION_HIGHLIGHT.
Major changes between versions 4.3.5 and 4.3.6
----------------------------------------------

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,