Implement canonical locking protocol

Suggested by: joerg
This commit is contained in:
Andrey A. Chernov 1997-08-10 18:42:39 +00:00
parent 3c3549f6e7
commit 84dc22996d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=28040
3 changed files with 83 additions and 62 deletions

View File

@ -18,7 +18,7 @@
* 5. Modifications may be freely made to this file providing the above
* conditions are met.
*
* $Id: libutil.h,v 1.8 1997/05/12 10:36:13 brian Exp $
* $Id: libutil.h,v 1.9 1997/05/19 10:04:15 peter Exp $
*/
#ifndef _LIBUTIL_H_
@ -51,7 +51,9 @@ __END_DECLS
#define UU_LOCK_OK (0)
#define UU_LOCK_OPEN_ERR (-1)
#define UU_LOCK_READ_ERR (-2)
#define UU_LOCK_SEEK_ERR (-3)
#define UU_LOCK_CREAT_ERR (-3)
#define UU_LOCK_WRITE_ERR (-4)
#define UU_LOCK_LINK_ERR (-5)
#define UU_LOCK_TRY_ERR (-6)
#endif /* !_LIBUTIL_H_ */

View File

@ -23,7 +23,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $Id: uucplock.3,v 1.6 1997/05/11 08:50:33 davidn Exp $
.\" $Id: uucplock.3,v 1.7 1997/05/12 10:36:14 brian Exp $
.\" "
.Dd March 30, 1997
.Os
@ -99,17 +99,21 @@ The lock file could not be opened via
The lock file could not be read via
.Xr read 2 .
.Pp
.Dv UU_LOCK_SEEK_ERR:
The lock file was
.Dq stale ,
but the call to
.Xr lseek 2
necessary to write the current process id failed.
.Dv UU_LOCK_CREAT_ERR:
Can't create temporary lock file via
.Xr creat 2 .
.Pp
.Dv UU_LOCK_WRITE_ERR:
The current process id could not be written to the lock file via a call to
.Xr write 2 .
.Pp
.Dv UU_LOCK_LINK_ERR:
Can't link temporary lock file via
.Xr link 2 .
.Pp
.Dv UU_LOCK_TRY_ERR:
Locking attempts are failed after 5 tries.
.Pp
If a value of
.Dv UU_LOCK_OK
is passed to

View File

@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: uucplock.c,v 1.6 1997/05/12 10:36:14 brian Exp $
* $Id: uucplock.c,v 1.7 1997/08/05 12:58:02 ache Exp $
*
*/
@ -50,72 +50,81 @@ static const char sccsid[] = "@(#)uucplock.c 8.1 (Berkeley) 6/6/93";
#include <string.h>
#include "libutil.h"
#define MAXTRIES 5
#define LOCKTMP "LCKTMP..%d"
#define LOCKFMT "LCK..%s"
#define GORET(level, val) { err = errno; uuerr = (val); \
goto __CONCAT(ret, level); }
/* Forward declarations */
static int put_pid (int fd, pid_t pid);
static pid_t get_pid (int fd,int *err);
/*
* uucp style locking routines
* return: 0 - success
* -1 - failure
*/
int uu_lock (const char *ttyname)
{
int fd;
int fd, tmpfd, i;
pid_t pid;
char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
int err;
char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN],
lcktmpname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
int err, uuerr;
(void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, ttyname);
fd = open(tbuf, O_RDWR|O_CREAT|O_EXCL|O_EXLOCK, 0660);
if (fd < 0) {
/*
* file is already locked
* check to see if the process holding the lock still exists
*/
fd = open(tbuf, O_RDWR|O_SHLOCK);
if (fd < 0)
return UU_LOCK_OPEN_ERR;
if ((pid = get_pid (fd, &err)) == -1) {
(void)close(fd);
errno = err;
return UU_LOCK_READ_ERR;
}
if (kill(pid, 0) == 0 || errno != ESRCH) {
(void)close(fd); /* process is still running */
return UU_LOCK_INUSE;
}
/*
* The process that locked the file isn't running, so
* we'll lock it ourselves
*/
if (lseek(fd, (off_t) 0, L_SET) < 0) {
err = errno;
(void)close(fd);
errno = err;
return UU_LOCK_SEEK_ERR;
}
if (flock(fd, LOCK_EX|LOCK_NB) < 0) {
(void)close(fd);
return UU_LOCK_INUSE;
}
/* fall out and finish the locking process */
}
pid = getpid();
if (!put_pid (fd, pid)) {
err = errno;
(void)unlink(tbuf);
(void)close(fd);
errno = err;
return UU_LOCK_WRITE_ERR;
(void)snprintf(lcktmpname, sizeof(lcktmpname), _PATH_UUCPLOCK LOCKTMP,
pid);
(void)snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT,
ttyname);
if ((tmpfd = creat(lcktmpname, 0664)) < 0)
GORET(0, UU_LOCK_CREAT_ERR);
for (i = 0; i < MAXTRIES; i++) {
if (link (lcktmpname, lckname) < 0) {
if (errno != EEXIST)
GORET(1, UU_LOCK_LINK_ERR);
/*
* file is already locked
* check to see if the process holding the lock
* still exists
*/
if ((fd = open(lckname, O_RDONLY)) < 0)
GORET(1, UU_LOCK_OPEN_ERR);
if ((pid = get_pid (fd, &err)) == -1)
GORET(2, UU_LOCK_READ_ERR);
close(fd);
if (kill(pid, 0) == 0 || errno != ESRCH)
GORET(1, UU_LOCK_INUSE);
/*
* The process that locked the file isn't running, so
* we'll lock it ourselves
*/
(void)unlink(lckname);
} else {
if (!put_pid (tmpfd, pid))
GORET(3, UU_LOCK_WRITE_ERR);
break;
}
}
GORET(1, (i >= MAXTRIES) ? UU_LOCK_TRY_ERR : UU_LOCK_OK);
ret3:
(void)unlink(lckname);
goto ret1;
ret2:
(void)close(fd);
return UU_LOCK_OK;
ret1:
(void)close(tmpfd);
(void)unlink(lcktmpname);
ret0:
errno = err;
return uuerr;
}
int uu_unlock (const char *ttyname)
@ -142,12 +151,18 @@ const char *uu_lockerr (int uu_lockresult)
case UU_LOCK_READ_ERR:
fmt = "read error: %s";
break;
case UU_LOCK_SEEK_ERR:
fmt = "seek error: %s";
case UU_LOCK_CREAT_ERR:
fmt = "creat error: %s";
break;
case UU_LOCK_WRITE_ERR:
fmt = "write error: %s";
break;
case UU_LOCK_LINK_ERR:
fmt = "link error: %s";
break;
case UU_LOCK_TRY_ERR:
fmt = "too many tries: %s";
break;
default:
fmt = "undefined error: %s";
break;
@ -166,7 +181,7 @@ static int put_pid (int fd, pid_t pid)
return write (fd, buf, len) == len;
}
static pid_t get_pid (int fd,int *err)
static pid_t get_pid (int fd, int *err)
{
int bytes_read;
char buf[32];