summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWayne Davison <wayned@users.sourceforge.net>2009-12-18 19:50:45 +0000
committerWayne Davison <wayned@users.sourceforge.net>2009-12-18 19:50:45 +0000
commit6e317e4b96cf708eee0841e7c8a599efdecb2af1 (patch)
tree36aea39a48029a6688c2961169e1fd455f0aace7
parent53557009925025b0c17d30511813b87bc2ce340a (diff)
downloadzsh-6e317e4b96cf708eee0841e7c8a599efdecb2af1.tar.gz
zsh-6e317e4b96cf708eee0841e7c8a599efdecb2af1.zip
Add symlink-based hist-file locking.
-rw-r--r--ChangeLog6
-rw-r--r--Src/hist.c32
-rw-r--r--configure.ac3
3 files changed, 37 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 5a94fae95..500257248 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-12-18 Wayne Davison <wayned@users.sourceforge.net>
+
+ * users/14659: Src/hist.c: Add symlink-based hist-file locking.
+
2009-12-17 Peter Stephenson <pws@csr.com>
* Greg: 27529: Completion/Unix/Command/_subversion: make URL
@@ -12514,5 +12518,5 @@
*****************************************************
* This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.4847 $
+* $Revision: 1.4848 $
*****************************************************
diff --git a/Src/hist.c b/Src/hist.c
index 86b08bd45..b1e4e82c4 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -2600,11 +2600,38 @@ lockhistfile(char *fn, int keep_trying)
int fd;
char *lockfile;
#ifdef HAVE_LINK
+# ifdef HAVE_SYMLINK
+ char pidbuf[32], *lnk;
+# else
char *tmpfile;
+# endif
#endif
lockfile = bicat(unmeta(fn), ".LOCK");
+ /* NOTE: only use symlink locking on a link()-having host in order to
+ * avoid a change from open()-based locking to symlink()-based. */
#ifdef HAVE_LINK
+# ifdef HAVE_SYMLINK
+ sprintf(pidbuf, "/pid-%ld/host-", (long)mypid);
+ lnk = bicat(pidbuf, getsparam("HOST"));
+ /* We'll abuse fd as our success flag. */
+ while ((fd = symlink(lnk, lockfile)) < 0) {
+ if (errno != EEXIST || !keep_trying)
+ break;
+ if (lstat(lockfile, &sb) < 0) {
+ if (errno == ENOENT)
+ continue;
+ break;
+ }
+ if (time(NULL) - sb.st_mtime < 10)
+ sleep(1);
+ else
+ unlink(lockfile);
+ }
+ if (fd < 0)
+ lockhistct--;
+ free(lnk);
+# else /* not HAVE_SYMLINK */
if ((fd = gettempfile(fn, 0, &tmpfile)) >= 0) {
FILE *out = fdopen(fd, "w");
if (out) {
@@ -2618,7 +2645,7 @@ lockhistfile(char *fn, int keep_trying)
lockfile, errno);
else if (!keep_trying)
;
- else if (stat(lockfile, &sb) < 0) {
+ else if (lstat(lockfile, &sb) < 0) {
if (errno == ENOENT)
continue;
zerr("failed to stat lock file %s: %e", lockfile, errno);
@@ -2635,11 +2662,12 @@ lockhistfile(char *fn, int keep_trying)
unlink(tmpfile);
free(tmpfile);
}
+# endif /* not HAVE_SYMLINK */
#else /* not HAVE_LINK */
while ((fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) {
if (errno != EEXIST || !keep_trying)
break;
- if (stat(lockfile, &sb) < 0) {
+ if (lstat(lockfile, &sb) < 0) {
if (errno == ENOENT)
continue;
break;
diff --git a/configure.ac b/configure.ac
index 569300765..262fe5d14 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1169,7 +1169,8 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \
htons ntohs \
regcomp regexec regerror regfree \
gdbm_open getxattr \
- realpath canonicalize_file_name)
+ realpath canonicalize_file_name \
+ symlink)
AC_FUNC_STRCOLL
if test x$enable_cap = xyes; then