Wanted: lockf system call source

Doug Gwyn gwyn at brl-smoke.ARPA
Fri Nov 14 01:54:19 AEST 1986


In article <110 at dvm.UUCP> dave at dvm.UUCP (David Brand) writes:
>I am looking for a copy of the source to a /usr/group compatible implementation
>of the lockf system call.  Is this available in the public domain?  If so, do I
>need a Unix source license to look at it?  I am interested in the table
>handling and deadlock detection code itself, not just the list of kernel
>modifications presented in the Bass article.

Code for the mods to 7th Edition UNIX is given in the "Reader's Guide
to the 1984 /usr/group Standard".  It includes the deadlock detector
etc.  I don't promise that it's bug-free.  This document does not
require any source license.  I assume /usr/group will sell you a copy.

Of course, UNIX System V has a more general record locking facility
accessible via fcntl().  You definitely need a source license for it.

If you're going to implement record locking, I recommend modeling it
after the System V facility, with lockf() just a library routine that
invokes the fcntl()s:

/*
	lockf -- system call emulation for 4.2BSD

	last edit:	21-Sep-1986	D A Gwyn

	See fcntl.c source for NOTES about the quality of emulation.
*/

#include	<errno.h>
#include	<fcntl.h>
#include	<unistd.h>

extern int	fcntl();


/*ARGSUSED*/
int
lockf( fildes, function, size )
	int		fildes;		/* file descriptor */
	int		function;	/* F_* code from <unistd.h> */
	long		size;		/* extent to be locked */
	{
	struct flock	fl;		/* data for fcntl() */

	fl.l_whence = SEEK_CUR;

	if ( size < 0L )
		{			/* this section thanks to Gould */
		fl.l_start = size;
		fl.l_len = -size;
		}
	else	{
		fl.l_start = 0L;
		fl.l_len = size;
		}

	switch ( function )
		{
	case F_ULOCK:			/* unlock region */
		fl.l_type = F_UNLCK;

		if ( fcntl( fildes, F_SETLK, (int)&fl ) == 0 )
			return 0;

		break;			/* EBADF | EINVAL */

	case F_LOCK:			/* lock region */
		fl.l_type = F_WRLCK;

		if ( fcntl( fildes, F_SETLKW, (int)&fl ) == 0 )
			return 0;

		break;			/* EBADF | EINVAL */

	case F_TLOCK:			/* test & lock region */
		fl.l_type = F_WRLCK;

		if ( fcntl( fildes, F_SETLK, (int)&fl ) == 0 )
			return 0;

		break;			/* EBADF | EINVAL | EAGAIN */

	case F_TEST:			/* test for lock */
		fl.l_type = F_RDLCK;	/* avoid spurious locking */
					/* (really should be F_WRLCK) */

		if ( fcntl( fildes, F_GETLK, (int)&fl ) == 0 )
			if ( fl.l_type == F_UNLCK )
				return 0;	/* no lock */
			else	{
				errno = EAGAIN;	/* EACCES in UNIX System V */
				return -1;	/* lock exists */
				}

		break;			/* EBADF | EINVAL */

	default:
		errno = EINVAL;		/* (spec fails to mention this) */
		return -1;
		}

	/* error return: */

	/* deadlock error is given if we run out of resources,
	   in compliance with /usr/group standards (thanks to Gould) */

	if ( errno == EMFILE || errno == ENOSPC || errno == ENOLCK )
		errno = EDEADLK;

	return -1;
	}



More information about the Comp.unix.wizards mailing list