⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lock.c

📁 早期freebsd实现
💻 C
字号:
/* lock.c - universal locking routines */#ifndef	lintstatic char ident[] = "@(#)$Id: lock.c,v 2.19 1993/08/25 17:33:09 jromine Exp $";#endif/* compile-time priority: *	LOCKF	use if defined *	FCNTL	use if SYS5  defined and LOCKF not defined *	FLOCK	use if BSD42 defined and LOCKF and SYS5 not defined */#ifdef	MMDFONLY#define	LOCKONLY#endif#include "../h/mh.h"#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 SVR4#define LOCKF#include <unistd.h>#endif#ifdef	LOCKF#include <sys/errno.h>#include <sys/file.h>#ifndef	F_ULOCK#ifdef	UNISTD#include <unistd.h>#else	/* UNISTD */#include <sys/fcntl.h>#endif	/* UNISTD */#endif#endif	/* LOCKF */#if defined(_AIX) || defined(AUX)#include <sys/file.h>#endif#ifdef	SYS5#define	u_short	ushort#define u_long  ulong#endif#if defined(SYS5) && !defined(_AIX)#define	index	strchr#define	rindex	strrchr#endif#ifdef	BSD42#define	FLOCK		/* LOCKF will override this, if defined */#endifextern int  errno;#ifdef	LOCKONLY#ifndef	MMDFONLYchar   *lockldir = "/usr/spool/locks";#endif	/* not MMDFONLY */#endif	/* LOCKONLY */static int	b_lkopen(), lockit(), f_lkopen();static		lockname(), timerON(), timerOFF();long	time ();/*  */int	lkopen (file, access)register char   *file;register int     access;{    mts_init ("mts");    switch (lockstyle) {	case LOK_UNIX:#if	defined (FLOCK) || defined(LOCKF) || defined(FCNTL)	    return f_lkopen (file, access);#endif	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;#if defined(hpux) || defined(ncr)    write(fd, "MH lock\n",8);#endif /* hpux */    (void) close (fd);    fd = link (tmp, file);    (void) unlink (tmp);    return (fd != NOTOK ? OK : NOTOK);}/*  */static  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 == 0)	cp = file;    if (lockldir == NULL || *lockldir == 0) {	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 == 0)	    (void) strcpy (tmplock, ",LCK.XXXXXX");	else	    (void) sprintf (tmplock, "%.*s,LCK.XXXXXX",		cp - curlock, curlock);	(void) unlink (mktemp (tmplock));    }}/*  */#if	defined(FLOCK) || defined(LOCKF) || defined(FCNTL)#if	defined(BSD42) || defined(SVR4)#include <sys/file.h>#if	defined(SUN40) || defined(SVR4)#include <sys/fcntl.h>#endif#else #ifdef	FCNTL#include <fcntl.h>#endif#endifstatic int  f_lkopen (file, access)register char   *file;register int     access;{    register int    fd,                    i,		    j;#ifdef FCNTL    struct flock    buf;#endif /* FCNTL */    for (i = 0; i < 5; i++) {#if defined(LOCKF) || defined(FCNTL)	j = access;	access &= ~O_APPEND;	/* make sure we open at the beginning */	if ((access & 03) == O_RDONLY) {	/* We MUST have write permission or lockf/fcntl() won't work */	/* (Stupid eh?) */	    access &= ~O_RDONLY;	    access |= O_RDWR;	}#endif	/* LOCKF || FCNTL */	if ((fd = open (file, access | O_NDELAY)) == NOTOK)	    return NOTOK;#ifndef	LOCKF#ifndef	FLOCK#ifndef	FCNTL	/* should be an error? */#else /* FCNTL */	buf.l_type = F_WRLCK;	buf.l_whence = 0;	buf.l_start = 0;	buf.l_len = 0;	if (fcntl (fd, F_SETLK, &buf) != NOTOK)	    return fd;#endif#else /* FLOCK */	if (flock (fd, LOCK_EX | LOCK_NB) != NOTOK)	    return fd;#endif#else /* LOCKF */	if (lockf (fd, F_TLOCK, 0L) != NOTOK) {	    /* see if we should be at the end */	    if (j & O_APPEND)#ifdef SVR4		lseek (fd, (off_t)0, SEEK_END);#else		lseek (fd, (off_t)0, L_XTND);#endif	    return fd;	}	/* Fix errno - lockf screws it */	if (errno == EACCES)	    errno = EWOULDBLOCK;#endif	j = errno;	(void) close (fd);	sleep (5);    }    (void) close (fd);    errno = j;    return NOTOK;}#endif	/* FLOCK || LOCKF || FCNTL *//*  *//* ARGSUSED */int     lkclose (fd, file)register int     fd;register char   *file;{    char    curlock[BUFSIZ];    struct stat st;#ifdef FCNTL    struct flock buf;#endif    if (fd == NOTOK)	return OK;    switch (lockstyle) {	case LOK_UNIX: #ifndef	LOCKF#ifndef	FLOCK#ifndef	FCNTL	/* should be an error? */#else	/* FCNTL */	    buf.l_type = F_UNLCK;	    buf.l_whence = 0;	    buf.l_start = 0;	    buf.l_len = 0;	    fcntl(fd, F_SETLK, &buf);	    break;#endif#else	/* FLOCK */	    flock (fd, LOCK_UN);	    break;#endif#else	/* LOCKF */	    lseek (fd, (off_t)0, L_SET); /* make sure we unlock the whole thing */	    lockf (fd, F_ULOCK, 0L);	    break;#endif		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 */int	lkfclose (fp, file)register FILE	*fp;register char	*file;{    char    curlock[BUFSIZ];    struct stat st;#ifdef FCNTL    struct flock buf;#endif    if (fp == NULL)	return OK;    switch (lockstyle) {	case LOK_UNIX: #ifndef	LOCKF#ifndef	FLOCK#ifndef	FCNTL	/* should be an error? */#else	/* FCNTL */	    buf.l_type = F_UNLCK;	    buf.l_whence = 0;	    buf.l_start = 0;	    buf.l_len = 0;	    fcntl(fileno(fp), F_SETLK, &buf);	    break;#endif#else /* FLOCK */	    flock (fileno(fp), LOCK_UN);	    break;#endif#else	/* LOCKF */	    fseek (fp, 0L, 0); /* make sure we unlock the whole thing */	    lockf (fileno(fp), F_ULOCK, 0L);	    break;#endif	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 TYPESIG 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 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 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);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -