|
|
BSD 4.3reno
/* @(#) $Header: /var/lib/cvsd/repos/CSRG/43BSDReno/contrib/mh/zotnet/mts/lock.c,v 1.1.1.1 2018/04/24 16:12:56 root Exp $ (LBL) */
/* lock.c - universal locking routines */
#ifdef MMDFONLY
#define LOCKONLY
#endif MMDFONLY
#include <stdio.h>
#ifndef LOCKONLY
#include "../h/strings.h"
#include "mts.h"
#else LOCKONLY
#include "strings.h"
#ifdef MMDFONLY
#include "mmdfonly.h"
#include "mts.h"
#else not MMDFONLY
#include "lockonly.h"
#endif not MMDFONLY
#endif LOCKONLY
#include <sys/types.h>
#include <sys/stat.h>
#ifdef SUNOS4
#include <sys/unistd.h>
#endif
#define NOTOK (-1)
#define OK 0
#define NULLCP ((char *) 0)
#ifdef SYS5
#define index strchr
#define rindex strrchr
#endif SYS5
#ifndef SIGDECL
#ifdef SUNOS4
#define SIGDECL void
#else
#define SIGDECL int
#endif
#endif
extern int errno;
#ifdef LOCKONLY
#ifndef MMDFONLY
char *lockldir = "/usr/spool/locks";
#endif not MMDFONLY
#endif LOCKONLY
long time();
static int b_lkopen(), lockit(), f_lkopen();
static void lockname(), timerON(), timerOFF();
/* */
lkopen(file, access)
register char *file;
register int access;
{
mts_init ("mts");
switch (lockstyle) {
case LOK_UNIX:
#ifdef BSD42
return f_lkopen (file, access);
#endif BSD42
default:
return b_lkopen (file, access);
}
}
/* */
static int
b_lkopen(file, access)
register char *file;
register int access;
{
register int i,
j;
long curtime;
char curlock[BUFSIZ],
tmplock[BUFSIZ];
struct stat st;
if (stat (file, &st) == NOTOK)
return NOTOK;
lockname (curlock, tmplock, file, (int) st.st_dev, (int) st.st_ino);
for (i = 0;;)
switch (lockit (tmplock, curlock)) {
case OK:
if ((i = open (file, access)) == NOTOK) {
j = errno;
(void) unlink (curlock);
errno = j;
}
timerON (curlock, i);
return i;
case NOTOK:
if (stat (curlock, &st) == NOTOK) {
if (i++ > 5)
return NOTOK;
sleep (5);
break;
}
i = 0;
(void) time (&curtime);
if (curtime < st.st_ctime + 60L)
sleep (5);
else
(void) unlink (curlock);
break;
}
}
static int
lockit(tmp, file)
register char *tmp, *file;
{
register int fd;
if ((fd = creat (tmp, 0400)) == NOTOK)
return NOTOK;
(void) close (fd);
fd = link (tmp, file);
(void) unlink (tmp);
return (fd != NOTOK ? OK : NOTOK);
}
/* */
static void
lockname(curlock, tmplock, file, dev, ino)
register char *curlock, *tmplock, *file;
register int dev, ino;
{
register char *bp,
*cp;
bp = curlock;
if ((cp = rindex (file, '/')) == NULL || *++cp == NULL)
cp = file;
if (lockldir == NULL || *lockldir == NULL) {
if (cp != file) {
(void) sprintf (bp, "%.*s", cp - file, file);
bp += strlen (bp);
}
}
else {
(void) sprintf (bp, "%s/", lockldir);
bp += strlen (bp);
}
switch (lockstyle) {
case LOK_BELL:
default:
(void) sprintf (bp, "%s.lock", cp);
break;
case LOK_MMDF:
(void) sprintf (bp, "LCK%05d.%05d", dev, ino);
break;
}
if (tmplock) {
if ((cp = rindex (curlock, '/')) == NULL || *++cp == NULL)
(void) strcpy (tmplock, ",LCK.XXXXXX");
else
(void) sprintf (tmplock, "%.*s,LCK.XXXXXX",
cp - curlock, curlock);
(void) unlink (mktemp (tmplock));
}
}
/* */
#ifdef BSD42
#include <sys/file.h>
#ifndef O_NDELAY
#include <fcntl.h>
#endif
static int
f_lkopen(file, access)
register char *file;
register int access;
{
register int fd,
i,
j;
#ifdef sun
/* Must force some kind of write access or else lockf() fails */
if (access == 0)
access = O_RDWR;
#endif
for (i = 0; i < 5; i++) {
if ((fd = open (file, access | O_NDELAY)) == NOTOK)
return NOTOK;
#ifndef sun
if (flock (fd, LOCK_EX | LOCK_NB) != NOTOK)
#else
if (lockf (fd, F_TLOCK, 0) != NOTOK)
#endif
return fd;
j = errno;
(void) close (fd);
sleep (5);
}
(void) close (fd);
errno = j;
return NOTOK;
}
#endif BSD42
/* */
/* ARGSUSED */
lkclose(fd, file)
register int fd;
register char *file;
{
char curlock[BUFSIZ];
struct stat st;
if (fd == NOTOK)
return OK;
switch (lockstyle) {
case LOK_UNIX:
#ifdef BSD42
break;
#endif BSD42
default:
if (fstat (fd, &st) != NOTOK) {
lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino);
(void) unlink (curlock);
timerOFF (fd);
}
}
return (close (fd));
}
/* */
FILE *
lkfopen(file, mode)
register char *file, *mode;
{
register int fd;
register FILE *fp;
if ((fd = lkopen (file, strcmp (mode, "r") ? 2 : 0)) == NOTOK)
return NULL;
if ((fp = fdopen (fd, mode)) == NULL) {
(void) close (fd);
return NULL;
}
return fp;
}
/* ARGSUSED */
lkfclose(fp, file)
register FILE *fp;
register char *file;
{
char curlock[BUFSIZ];
struct stat st;
if (fp == NULL)
return OK;
switch (lockstyle) {
case LOK_UNIX:
#ifdef BSD42
break;
#endif BSD42
default:
if (fstat (fileno (fp), &st) != NOTOK) {
lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino);
(void) unlink (curlock);
}
}
return (fclose (fp));
}
/* */
#include <signal.h>
#define NSECS ((unsigned) 20)
struct lock {
int l_fd;
char *l_lock;
struct lock *l_next;
};
#define NULLP ((struct lock *) 0)
static struct lock *l_top = NULLP;
/* ARGSUSED */
static SIGDECL
alrmser(sig)
int sig;
{
register int j;
register char *cp;
register struct lock *lp;
#ifndef BSD42
(void) signal (SIGALRM, alrmser);
#endif BSD42
for (lp = l_top; lp; lp = lp -> l_next)
if (*(cp = lp -> l_lock) && (j = creat (cp, 0400)) != NOTOK)
(void) close (j);
(void) alarm (NSECS);
}
/* */
static void
timerON(lock, fd)
char *lock;
int fd;
{
register struct lock *lp;
if ((lp = (struct lock *) malloc ((unsigned) (sizeof *lp))) == NULLP)
return; /* XXX */
lp -> l_fd = fd;
if ((lp -> l_lock = malloc ((unsigned) (strlen (lock) + 1))) == NULLCP) {
free ((char *) lp);
return; /* XXX */
}
(void) strcpy (lp -> l_lock, lock);
lp -> l_next = NULLP;
if (l_top)
lp -> l_next = l_top -> l_next;
else {
(void) signal (SIGALRM, alrmser);/* perhaps SIGT{STP,TIN,TOU} */
(void) alarm (NSECS);
}
l_top = lp;
}
static void
timerOFF(fd)
int fd;
{
register struct lock *pp,
*lp;
(void) alarm (0);
if (l_top) {
for (pp = lp = l_top; lp; pp = lp, lp = lp -> l_next)
if (lp -> l_fd == fd)
break;
if (lp) {
if (lp == l_top)
l_top = lp -> l_next;
else
pp -> l_next = lp -> l_next;
free (lp -> l_lock);
free ((char *) lp);
}
}
if (l_top)
(void) alarm (NSECS);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.