From e3f764d1ef4377ccec978a43051c36e15179a754 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 22 Jun 2010 11:00:31 +0000 Subject: 28047: attempt to make locking with fc command more useful --- ChangeLog | 9 ++++- Completion/Zsh/Command/_zstyle | 19 +++++++++- Src/hist.c | 82 +++++++++++++++++++++++++++++------------- 3 files changed, 84 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index c7adff843..3b5fd9c33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2010-06-22 Peter Stephenson + + * 28047: Src/hist.c: make fc -R/-W more consistently verbose + and allow fc -R to work if file could be read but permissions + didn't allow it to be locked (as distinct from failing to lock + it because something else had locked it). + 2010-06-22 Doug Kearns * 28052: Completion/Unix/Command/_cvs: remove duplicated completion of @@ -13320,5 +13327,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5012 $ +* $Revision: 1.5013 $ ***************************************************** diff --git a/Completion/Zsh/Command/_zstyle b/Completion/Zsh/Command/_zstyle index 6e34fcc4b..dcf30c083 100644 --- a/Completion/Zsh/Command/_zstyle +++ b/Completion/Zsh/Command/_zstyle @@ -23,6 +23,7 @@ _completers() { # Assoc array of styles; the values give the possible top-level # contexts: # c completion +# d chpwd # e line editor # z zftp # or any combination of the above, @@ -104,6 +105,7 @@ styles=( prefix-needed c:bool preserve-prefix c:preserve-prefix range c: + recent-dirs-insert c:recent-dirs-insert regular c:bool remote-access c:bool remove-all-dups c:bool @@ -131,6 +133,12 @@ styles=( verbose ce:bool word c:bool + recent-dirs-default d:bool + recent-dirs-file d:_files + recent-dirs-max d: + recent-dirs-prune d: + recent-dirs-pushd d:bool + auto-previous e:bool break-keys e: cursor e: @@ -219,6 +227,10 @@ while (( $#state )); do ctop=c ;; + (:chwpd:*) + ctop=d + ;; + (:zftp:*) ctop=z ;; @@ -228,7 +240,7 @@ while (( $#state )); do ;; (*) - ctop=cez + ctop=cdez ;; esac _wanted styles expl style \ @@ -422,6 +434,11 @@ while (( $#state )); do _message -e prefixes 'pattern matching prefix to keep' ;; + (recent-dirs-insert) + _wanted values expl 'inserting recent directories' \ + compadd true false always fallback both + ;; + (separator) _message -e separators 'separator string' ;; diff --git a/Src/hist.c b/Src/hist.c index ee5422cc9..5ff448340 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -1194,7 +1194,7 @@ hend(Eprog prog) callhookfunc("zshaddhistory", hookargs, 1, &hookret); /* For history sharing, lock history file once for both read and write */ hf = getsparam("HISTFILE"); - if (isset(SHAREHISTORY) && lockhistfile(hf, 0)) { + if (isset(SHAREHISTORY) && !lockhistfile(hf, 0)) { readhistfile(hf, 0, HFILE_USE_OPTIONS | HFILE_FAST); curline.histnum = curhist+1; } @@ -2231,20 +2231,25 @@ readhistfile(char *fn, int err, int readflags) short *wordlist; struct stat sb; int nwordpos, nwordlist, bufsiz; - int searching, newflags, l; + int searching, newflags, l, ret; if (!fn && !(fn = getsparam("HISTFILE"))) return; if (readflags & HFILE_FAST) { if (stat(unmeta(fn), &sb) < 0 || (lasthist.fsiz == sb.st_size && lasthist.mtim == sb.st_mtime) - || !lockhistfile(fn, 0)) + || lockhistfile(fn, 0)) return; lasthist.fsiz = sb.st_size; lasthist.mtim = sb.st_mtime; + } else if ((ret = lockhistfile(fn, 1))) { + if (ret == 2) { + zwarn("locking failed for %s: %e: reading anyway", fn, errno); + } else { + zerr("locking failed for %s: %e", fn, errno); + return; + } } - else if (!lockhistfile(fn, 1)) - return; if ((in = fopen(unmeta(fn), "r"))) { nwordlist = 64; wordlist = (short *)zalloc(nwordlist*sizeof(short)); @@ -2377,6 +2382,11 @@ readhistfile(char *fn, int err, int readflags) #ifdef HAVE_FCNTL_H static int flock_fd = -1; +/* + * Lock file using fcntl(). Return 0 on success, 1 on failure of + * locking mechanism, 2 on permanent failure (e.g. permission). + */ + static int flockhistfile(char *fn, int keep_trying) { @@ -2384,7 +2394,7 @@ flockhistfile(char *fn, int keep_trying) int ctr = keep_trying ? 9 : 0; if ((flock_fd = open(unmeta(fn), O_RDWR | O_NOCTTY)) < 0) - return errno == ENOENT; /* "successfully" locked missing file */ + return errno == ENOENT ? 0 : 2; /* "successfully" locked missing file */ lck.l_type = F_WRLCK; lck.l_whence = SEEK_SET; @@ -2395,12 +2405,12 @@ flockhistfile(char *fn, int keep_trying) if (--ctr < 0) { close(flock_fd); flock_fd = -1; - return 0; + return 1; } sleep(1); } - return 1; + return 0; } #endif @@ -2424,14 +2434,16 @@ savehistfile(char *fn, int err, int writeflags) lasthist.next_write_ev = he->histnum + 1; he = down_histent(he); } - if (!he || !lockhistfile(fn, 0)) + if (!he || lockhistfile(fn, 0)) return; if (histfile_linect > savehistsiz + savehistsiz / 5) writeflags &= ~HFILE_FAST; } else { - if (!lockhistfile(fn, 1)) + if (lockhistfile(fn, 1)) { + zerr("locking failed for %s: %e", fn, errno); return; + } he = hist_ring->down; } if (writeflags & HFILE_USE_OPTIONS) { @@ -2597,18 +2609,27 @@ savehistfile(char *fn, int err, int writeflags) static int lockhistct; +/* + * Lock history file. Return 0 on success, 1 on failure to lock this + * time, 2 on permanent failure (e.g. permission). + */ + /**/ int lockhistfile(char *fn, int keep_trying) { int ct = lockhistct; + int ret = 0; if (!fn && !(fn = getsparam("HISTFILE"))) - return 0; + return 1; #ifdef HAVE_FCNTL_H - if (isset(HISTFCNTLLOCK) && flock_fd < 0 && !flockhistfile(fn, keep_trying)) - return 0; + if (isset(HISTFCNTLLOCK) && flock_fd < 0) { + ret = flockhistfile(fn, keep_trying); + if (ret) + return ret; + } #endif if (!lockhistct++) { @@ -2632,8 +2653,13 @@ lockhistfile(char *fn, int keep_trying) lnk = bicat(pidbuf, getsparam("HOST")); /* We'll abuse fd as our success flag. */ while ((fd = symlink(lnk, lockfile)) < 0) { - if (errno != EEXIST || !keep_trying) + if (errno != EEXIST) { + ret = 2; + break; + } else if (!keep_trying) { + ret = 1; break; + } if (lstat(lockfile, &sb) < 0) { if (errno == ENOENT) continue; @@ -2656,15 +2682,16 @@ lockhistfile(char *fn, int keep_trying) } else close(fd); while (link(tmpfile, lockfile) < 0) { - if (errno != EEXIST) - zerr("failed to create hard link as lock file %s: %e", - lockfile, errno); - else if (!keep_trying) - ; - else if (lstat(lockfile, &sb) < 0) { + if (errno != EEXIST) { + ret = 2; + break; + } else if (!keep_trying) { + ret = 1; + break; + } else if (lstat(lockfile, &sb) < 0) { if (errno == ENOENT) continue; - zerr("failed to stat lock file %s: %e", lockfile, errno); + ret = 2; } else { if (time(NULL) - sb.st_mtime < 10) sleep(1); @@ -2681,11 +2708,17 @@ lockhistfile(char *fn, int keep_trying) # 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) + if (errno != EEXIST) { + ret = 2; break; + } else if (!keep_trying) { + ret = 1; + break; + } if (lstat(lockfile, &sb) < 0) { if (errno == ENOENT) continue; + ret = 2; break; } if (time(NULL) - sb.st_mtime < 10) @@ -2714,9 +2747,10 @@ lockhistfile(char *fn, int keep_trying) flock_fd = -1; } #endif - return 0; + DPUTS(ret == 0, "BUG: return value non-zero on locking error"); + return ret; } - return 1; + return 0; } /* Unlock the history file if this corresponds to the last nested lock -- cgit 1.4.1