File tcsh-6.22.02-local-dotlock.dif of Package tcsh

Avoid left over dot lock file after reboot

---
 dotlock.c |  124 ++++++++++++++------------------------------------------------
 dotlock.h |    2 -
 sh.hist.c |   11 +++--
 3 files changed, 36 insertions(+), 101 deletions(-)

--- dotlock.c
+++ dotlock.c	2020-02-19 12:07:22.228255145 +0000
@@ -29,7 +29,9 @@
 #ifndef O_SYNC
 #define O_SYNC	0
 #endif
-
+#include <unistd.h>
+#include <fcntl.h>
+ 
 #include "dotlock.h"
 
 static int create_exclusive(const char *);
@@ -46,77 +48,26 @@ static int create_exclusive(const char *
 static int
 create_exclusive(const char *fname)
 {
-	char path[MAXPATHLEN], hostname[MAXHOSTNAMELEN + 1];
-	const char *ptr;
-	struct timeval tv;
-	pid_t pid;
-	size_t ntries, cookie;
-	int fd, serrno;
-	struct stat st;
-
-	(void)gettimeofday(&tv, NULL);
-	(void)gethostname(hostname, sizeof(hostname));
-	hostname[sizeof(hostname) - 1] = '\0';
-	pid = getpid();
-
-	cookie = pid ^ tv.tv_usec;
-
-	/*
-	 * We generate a semi-unique filename, from hostname.(pid ^ usec)
-	 */
-	if ((ptr = strrchr(fname, '/')) == NULL)
-		ptr = fname;
-	else
-		ptr++;
-
-	(void)snprintf(path, sizeof(path), "%.*s.%s.%lx",
-	    (int)(ptr - fname), fname, hostname, (u_long)cookie);
-
-	/*
-	 * We try to create the unique filename.
-	 */
-	for (ntries = 0; ntries < 5; ntries++) {
-		fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_SYNC, 0);
-		if (fd != -1) {
-			(void)close(fd);
+    	struct flock fl = { F_WRLCK, SEEK_SET, 0, 0, getpid()};
+	int fd, retval;
+
+	fd = open(fname, O_WRONLY|O_CREAT|O_SYNC, S_IWUSR);
+	if (fd < 0)
+		return -1;
+	do {
+		int ret;
+		retval = fcntl(fd, F_SETLKW, &fl);
+		if (retval < 0) {
+			if (errno == EINTR)
+				continue;
+			close(fd);
+			fd = -1;
 			break;
 		}
-		else if (errno == EEXIST)
-			continue;
-		else
-			return -1;
-	}
-
-	/*
-	 * We link the path to the name
-	 */
-	if (link(path, fname) == -1)
-		goto bad;
-
-	/*
-	 * Note that we stat our own exclusively created name, not the
-	 * destination, since the destination can be affected by others.
-	 */
-	if (stat(path, &st) == -1)
-		goto bad;
-
-	(void)unlink(path);
-
-	/*
-	 * If the number of links was two (one for the unique file and one
-	 * for the lock), we've won the race
-	 */
-	if (st.st_nlink != 2) {
-		errno = EEXIST;
-		return -1;
-	}
-	return 0;
+	} while (retval < 0);
 
-bad:
-	serrno = errno;
-	(void)unlink(path);
-	errno = serrno;
-	return -1;
+	(void)unlink(fname);
+	return fd;
 }
 
 /*
@@ -143,37 +94,18 @@ dot_lock(const char *fname, int pollinte
 	(void)snprintf(path, sizeof(path), "%s.lock", fname);
 
 	retval = -1;
-	for (;;) {
-		handle_pending_signals();
-		(void)sigprocmask(SIG_BLOCK, &nset, &oset);
-		if (create_exclusive(path) != -1) {
-			(void)sigprocmask(SIG_SETMASK, &oset, NULL);
-			retval = 0;
-			break;
-		}
-		else
-			(void)sigprocmask(SIG_SETMASK, &oset, NULL);
-
-		if (errno != EEXIST)
-			break;
-
-		if (pollinterval) {
-			if (pollinterval == -1) {
-				errno = EEXIST;
-				break;
-			}
-			(void)usleep((unsigned int)pollinterval * 1000);
-		}
-	}
+	handle_pending_signals();
+	(void)sigprocmask(SIG_BLOCK, &nset, &oset);
+	retval = create_exclusive(path);
+	(void)sigprocmask(SIG_SETMASK, &oset, NULL);
 	handle_pending_signals();
 	return retval;
 }
 
 void
-dot_unlock(const char *fname)
+dot_unlock(const int fd)
 {
-	char path[MAXPATHLEN];
-
-	(void)snprintf(path, sizeof(path), "%s.lock", fname);
-	(void)unlink(path);
+    	struct flock fl = { F_UNLCK, SEEK_SET, 0, 0, getpid()};
+	fcntl(fd, F_SETLK, &fl);
+	close(fd);
 }
--- dotlock.h
+++ dotlock.h	2020-02-19 09:40:16.034422159 +0000
@@ -30,6 +30,6 @@
  * pollinterval -- Interval (miliseconds) to check for lock, -1 return
  */
 int dot_lock(const char *fname, int pollinterval);
-void dot_unlock(const char *fname);
+void dot_unlock(const int fd);
 
 #endif /* #ifndef _DOTLOCK_H_ */
--- sh.hist.c
+++ sh.hist.c	2020-02-19 09:48:57.640589111 +0000
@@ -1230,9 +1230,11 @@ fmthist(int fmt, ptr_t ptr)
 }
 
 static void
-dotlock_cleanup(void* lockpath)
+dotlock_cleanup(void* xfdp)
 {
-	dot_unlock((char*)lockpath);
+	int *fdp;
+	fdp = xfdp;
+	dot_unlock(*fdp);
 }
 
 /* Save history before exiting the shell. */
@@ -1311,11 +1313,12 @@ rechist(Char *fname, int ref)
 	    jmp_buf_t osetexit;
 	    if (lock) {
 #ifndef WINNT_NATIVE
+		int fdlk;
 		char *lockpath = strsave(short2str(fname));
 		cleanup_push(lockpath, xfree);
 		/* Poll in 100 miliseconds interval to obtain the lock. */
-		if ((dot_lock(lockpath, 100) == 0))
-		    cleanup_push(lockpath, dotlock_cleanup);
+		if ((fdlk = dot_lock(lockpath, 100)) != -1)
+		    cleanup_push(&fdlk, dotlock_cleanup);
 #endif
 	    }
 	    getexit(osetexit);
openSUSE Build Service is sponsored by