mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-23 17:01:05 +02:00
24818: add HIST_FCNTL_LOCK.
unposted: update NEWS with new features
This commit is contained in:
parent
35cedab218
commit
78ce07b49f
7 changed files with 141 additions and 6 deletions
|
@ -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>
|
2008-04-16 Clint Adams <clint@zsh.org>
|
||||||
|
|
||||||
* 248??: Completion/Unix/Command/_git: some fixes and updates for
|
* 248??: Completion/Unix/Command/_git: some fixes and updates for
|
||||||
|
|
|
@ -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
|
events, otherwise this option will behave just like
|
||||||
tt(HIST_IGNORE_ALL_DUPS) once the history fills up with unique events.
|
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)
|
pindex(HIST_FIND_NO_DUPS)
|
||||||
cindex(history, ignoring duplicates in search)
|
cindex(history, ignoring duplicates in search)
|
||||||
item(tt(HIST_FIND_NO_DUPS))(
|
item(tt(HIST_FIND_NO_DUPS))(
|
||||||
|
|
|
@ -2046,7 +2046,8 @@ sect(How does zsh handle multibyte input and output?)
|
||||||
all terminals handle this, even if they correctly display the base
|
all terminals handle this, even if they correctly display the base
|
||||||
multibyte character, this option is not on by default. The KDE terminal
|
multibyte character, this option is not on by default. The KDE terminal
|
||||||
emulator tt(konsole), tt(rxvt-unicode), and the Unicode version of
|
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
|
The tt(COMBINING_CHARS) option only affects output; combining characters
|
||||||
may always be input, but when the option is off will be displayed
|
may always be input, but when the option is off will be displayed
|
||||||
|
|
16
NEWS
16
NEWS
|
@ -4,6 +4,22 @@ CHANGES FROM PREVIOUS VERSIONS OF ZSH
|
||||||
|
|
||||||
Note also the list of incompatibilities in the README file.
|
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
|
Major changes between versions 4.3.5 and 4.3.6
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
|
|
109
Src/hist.c
109
Src/hist.c
|
@ -2021,6 +2021,20 @@ readhistfile(char *fn, int err, int readflags)
|
||||||
else if (!lockhistfile(fn, 1))
|
else if (!lockhistfile(fn, 1))
|
||||||
return;
|
return;
|
||||||
if ((in = fopen(unmeta(fn), "r"))) {
|
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;
|
nwordlist = 64;
|
||||||
wordlist = (short *)zalloc(nwordlist*sizeof(short));
|
wordlist = (short *)zalloc(nwordlist*sizeof(short));
|
||||||
bufsiz = 1024;
|
bufsiz = 1024;
|
||||||
|
@ -2149,6 +2163,68 @@ readhistfile(char *fn, int err, int readflags)
|
||||||
unlockhistfile(fn);
|
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
|
void
|
||||||
savehistfile(char *fn, int err, int writeflags)
|
savehistfile(char *fn, int err, int writeflags)
|
||||||
|
@ -2158,6 +2234,9 @@ savehistfile(char *fn, int err, int writeflags)
|
||||||
Histent he;
|
Histent he;
|
||||||
zlong xcurhist = curhist - !!(histactive & HA_ACTIVE);
|
zlong xcurhist = curhist - !!(histactive & HA_ACTIVE);
|
||||||
int extended_history = isset(EXTENDEDHISTORY);
|
int extended_history = isset(EXTENDEDHISTORY);
|
||||||
|
#ifdef HAVE_FTRUNCATE
|
||||||
|
int truncate_history = 0;
|
||||||
|
#endif
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!interact || savehistsiz <= 0 || !hist_ring
|
if (!interact || savehistsiz <= 0 || !hist_ring
|
||||||
|
@ -2196,12 +2275,16 @@ savehistfile(char *fn, int err, int writeflags)
|
||||||
tmpfile = NULL;
|
tmpfile = NULL;
|
||||||
out = fd >= 0 ? fdopen(fd, "a") : NULL;
|
out = fd >= 0 ? fdopen(fd, "a") : NULL;
|
||||||
} else if (!isset(HISTSAVEBYCOPY)) {
|
} 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;
|
tmpfile = NULL;
|
||||||
out = fd >= 0 ? fdopen(fd, "w") : NULL;
|
out = fd >= 0 ? fdopen(fd, "w") : NULL;
|
||||||
|
#ifdef HAVE_FTRUNCATE
|
||||||
|
/* The file should be truncated after its locking. */
|
||||||
|
truncate_history = 1;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
tmpfile = bicat(unmeta(fn), ".new");
|
tmpfile = bicat(unmeta(fn), ".new");
|
||||||
if (unlink(tmpfile) < 0 && errno != ENOENT)
|
if (safe_unlink(tmpfile))
|
||||||
out = NULL;
|
out = NULL;
|
||||||
else {
|
else {
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
@ -2239,7 +2322,18 @@ savehistfile(char *fn, int err, int writeflags)
|
||||||
#endif
|
#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) {
|
if (out) {
|
||||||
|
#ifdef HAVE_FTRUNCATE
|
||||||
|
if (truncate_history)
|
||||||
|
ftruncate(fileno(out), 0);
|
||||||
|
#endif
|
||||||
ret = 0;
|
ret = 0;
|
||||||
for (; he && he->histnum <= xcurhist; he = down_histent(he)) {
|
for (; he && he->histnum <= xcurhist; he = down_histent(he)) {
|
||||||
if ((writeflags & HFILE_SKIPDUPS && he->node.flags & HIST_DUP)
|
if ((writeflags & HFILE_SKIPDUPS && he->node.flags & HIST_DUP)
|
||||||
|
@ -2285,16 +2379,19 @@ savehistfile(char *fn, int err, int writeflags)
|
||||||
zsfree(lasthist.text);
|
zsfree(lasthist.text);
|
||||||
lasthist.text = ztrdup(start);
|
lasthist.text = ztrdup(start);
|
||||||
}
|
}
|
||||||
}
|
} else if (ret >= 0 && fflush(out) < 0) {
|
||||||
if (fclose(out) < 0 && ret >= 0)
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
}
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
if (tmpfile) {
|
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);
|
zerr("can't rename %s.new to $HISTFILE", fn);
|
||||||
free(tmpfile);
|
free(tmpfile);
|
||||||
tmpfile = NULL;
|
tmpfile = NULL;
|
||||||
}
|
}
|
||||||
|
fclose(out);
|
||||||
|
|
||||||
if (writeflags & HFILE_SKIPOLD
|
if (writeflags & HFILE_SKIPOLD
|
||||||
&& !(writeflags & (HFILE_FAST | HFILE_NO_REWRITE))) {
|
&& !(writeflags & (HFILE_FAST | HFILE_NO_REWRITE))) {
|
||||||
|
@ -2314,6 +2411,8 @@ savehistfile(char *fn, int err, int writeflags)
|
||||||
pophiststack();
|
pophiststack();
|
||||||
histactive = remember_histactive;
|
histactive = remember_histactive;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
fclose(out);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
|
@ -135,6 +135,7 @@ static struct optname optns[] = {
|
||||||
{{NULL, "histallowclobber", 0}, HISTALLOWCLOBBER},
|
{{NULL, "histallowclobber", 0}, HISTALLOWCLOBBER},
|
||||||
{{NULL, "histbeep", OPT_ALL}, HISTBEEP},
|
{{NULL, "histbeep", OPT_ALL}, HISTBEEP},
|
||||||
{{NULL, "histexpiredupsfirst",0}, HISTEXPIREDUPSFIRST},
|
{{NULL, "histexpiredupsfirst",0}, HISTEXPIREDUPSFIRST},
|
||||||
|
{{NULL, "histfcntllock", 0}, HISTFCNTLLOCK},
|
||||||
{{NULL, "histfindnodups", 0}, HISTFINDNODUPS},
|
{{NULL, "histfindnodups", 0}, HISTFINDNODUPS},
|
||||||
{{NULL, "histignorealldups", 0}, HISTIGNOREALLDUPS},
|
{{NULL, "histignorealldups", 0}, HISTIGNOREALLDUPS},
|
||||||
{{NULL, "histignoredups", 0}, HISTIGNOREDUPS},
|
{{NULL, "histignoredups", 0}, HISTIGNOREDUPS},
|
||||||
|
|
|
@ -1749,6 +1749,7 @@ enum {
|
||||||
HISTALLOWCLOBBER,
|
HISTALLOWCLOBBER,
|
||||||
HISTBEEP,
|
HISTBEEP,
|
||||||
HISTEXPIREDUPSFIRST,
|
HISTEXPIREDUPSFIRST,
|
||||||
|
HISTFCNTLLOCK,
|
||||||
HISTFINDNODUPS,
|
HISTFINDNODUPS,
|
||||||
HISTIGNOREALLDUPS,
|
HISTIGNOREALLDUPS,
|
||||||
HISTIGNOREDUPS,
|
HISTIGNOREDUPS,
|
||||||
|
|
Loading…
Reference in a new issue