1 /* lock.c - universal locking routines */
3 static char ident[] = "@(#)$Id: lock.c,v 2.19 1993/08/25 17:33:09 jromine Exp $";
5 /* compile-time priority:
7 * FCNTL use if SYS5 defined and LOCKF not defined
8 * FLOCK use if BSD42 defined and LOCKF and SYS5 not defined
18 #include "../h/strings.h"
25 #else /* not MMDFONLY */
27 #endif /* not MMDFONLY */
29 #include <sys/types.h>
36 #include <sys/errno.h>
42 #include <sys/fcntl.h>
46 #if defined(_AIX) || defined(AUX)
51 #define u_short ushort
56 #if defined(SYS5) && !defined(_AIX)
58 #define rindex strrchr
61 #define FLOCK /* LOCKF will override this, if defined */
68 char *lockldir = "/usr/spool/locks";
69 #endif /* not MMDFONLY */
72 static int b_lkopen(), lockit(), f_lkopen();
73 static lockname(), timerON(), timerOFF();
79 int lkopen (file, access)
86 #if defined (FLOCK) || defined(LOCKF) || defined(FCNTL)
87 return f_lkopen (file, access);
91 return b_lkopen (file, access);
97 static int b_lkopen (file, access)
104 char curlock[BUFSIZ],
108 if (stat (file, &st) == NOTOK)
110 lockname (curlock, tmplock, file, (int) st.st_dev, (int) st.st_ino);
113 switch (lockit (tmplock, curlock)) {
115 if ((i = open (file, access)) == NOTOK) {
117 (void) unlink (curlock);
120 timerON (curlock, i);
124 if (stat (curlock, &st) == NOTOK) {
132 (void) time (&curtime);
133 if (curtime < st.st_ctime + 60L)
136 (void) unlink (curlock);
142 static int lockit (tmp, file)
148 if ((fd = creat (tmp, 0400)) == NOTOK)
150 #if defined(hpux) || defined(ncr)
151 write(fd, "MH lock\n",8);
155 fd = link (tmp, file);
158 return (fd != NOTOK ? OK : NOTOK);
163 static lockname (curlock, tmplock, file, dev, ino)
164 register char *curlock,
174 if ((cp = rindex (file, '/')) == NULL || *++cp == 0)
176 if (lockldir == NULL || *lockldir == 0) {
178 (void) sprintf (bp, "%.*s", cp - file, file);
183 (void) sprintf (bp, "%s/", lockldir);
190 (void) sprintf (bp, "%s.lock", cp);
194 (void) sprintf (bp, "LCK%05d.%05d", dev, ino);
199 if ((cp = rindex (curlock, '/')) == NULL || *++cp == 0)
200 (void) strcpy (tmplock, ",LCK.XXXXXX");
202 (void) sprintf (tmplock, "%.*s,LCK.XXXXXX",
203 cp - curlock, curlock);
204 (void) unlink (mktemp (tmplock));
210 #if defined(FLOCK) || defined(LOCKF) || defined(FCNTL)
212 #if defined(BSD42) || defined(SVR4)
213 #include <sys/file.h>
214 #if defined(SUN40) || defined(SVR4)
215 #include <sys/fcntl.h>
223 static int f_lkopen (file, access)
234 for (i = 0; i < 5; i++) {
235 #if defined(LOCKF) || defined(FCNTL)
237 access &= ~O_APPEND; /* make sure we open at the beginning */
238 if ((access & 03) == O_RDONLY) {
239 /* We MUST have write permission or lockf/fcntl() won't work */
244 #endif /* LOCKF || FCNTL */
245 if ((fd = open (file, access | O_NDELAY)) == NOTOK)
250 /* should be an error? */
252 buf.l_type = F_WRLCK;
256 if (fcntl (fd, F_SETLK, &buf) != NOTOK)
260 if (flock (fd, LOCK_EX | LOCK_NB) != NOTOK)
264 if (lockf (fd, F_TLOCK, 0L) != NOTOK) {
265 /* see if we should be at the end */
268 lseek (fd, (off_t)0, SEEK_END);
270 lseek (fd, (off_t)0, L_XTND);
274 /* Fix errno - lockf screws it */
288 #endif /* FLOCK || LOCKF || FCNTL */
294 int lkclose (fd, file)
298 char curlock[BUFSIZ];
311 /* should be an error? */
313 buf.l_type = F_UNLCK;
317 fcntl(fd, F_SETLK, &buf);
325 lseek (fd, (off_t)0, L_SET); /* make sure we unlock the whole thing */
326 lockf (fd, F_ULOCK, 0L);
331 if (fstat (fd, &st) != NOTOK) {
332 lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino);
333 (void) unlink (curlock);
344 FILE *lkfopen (file, mode)
351 if ((fd = lkopen (file, strcmp (mode, "r") ? 2 : 0)) == NOTOK)
354 if ((fp = fdopen (fd, mode)) == NULL) {
365 int lkfclose (fp, file)
369 char curlock[BUFSIZ];
383 /* should be an error? */
385 buf.l_type = F_UNLCK;
389 fcntl(fileno(fp), F_SETLK, &buf);
393 flock (fileno(fp), LOCK_UN);
397 fseek (fp, 0L, 0); /* make sure we unlock the whole thing */
398 lockf (fileno(fp), F_ULOCK, 0L);
403 if (fstat (fileno (fp), &st) != NOTOK) {
404 lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino);
405 (void) unlink (curlock);
409 return (fclose (fp));
416 #define NSECS ((unsigned) 20)
424 #define NULLP ((struct lock *) 0)
426 static struct lock *l_top = NULLP;
431 static TYPESIG alrmser (sig)
436 register struct lock *lp;
439 (void) signal (SIGALRM, alrmser);
442 for (lp = l_top; lp; lp = lp -> l_next)
443 if (*(cp = lp -> l_lock) && (j = creat (cp, 0400)) != NOTOK)
446 (void) alarm (NSECS);
451 static timerON (lock, fd)
455 register struct lock *lp;
457 if ((lp = (struct lock *) malloc ((unsigned) (sizeof *lp))) == NULLP)
461 if ((lp -> l_lock = malloc ((unsigned) (strlen (lock) + 1))) == NULLCP) {
465 (void) strcpy (lp -> l_lock, lock);
466 lp -> l_next = NULLP;
469 lp -> l_next = l_top -> l_next;
471 (void) signal (SIGALRM, alrmser);/* perhaps SIGT{STP,TIN,TOU} */
472 (void) alarm (NSECS);
481 register struct lock *pp,
487 for (pp = lp = l_top; lp; pp = lp, lp = lp -> l_next)
488 if (lp -> l_fd == fd)
492 l_top = lp -> l_next;
494 pp -> l_next = lp -> l_next;
502 (void) alarm (NSECS);