mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-10-29 17:31:02 +01: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
				
			
		
							
								
								
									
										109
									
								
								Src/hist.c
									
										
									
									
									
								
							
							
						
						
									
										109
									
								
								Src/hist.c
									
										
									
									
									
								
							|  | @ -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; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue