This is afposlock.c in view mode; [Download] [Up]
/*
* $Author: cck $ $Date: 88/03/28 17:25:35 $
* $Header: afposlock.c,v 1.13 88/03/28 17:25:35 cck Rel $
* $Revision: 1.13 $
*/
/*
* afposlock.c - Appletalk Filing Protocol OS Interface for Byte Range Lock
* and other file lock routines
*
* Three cases: (a) have flock, (b) have lockf, and have (c) lockf and flock
* For A: can't do byte range lock
* For B: can't lock out writers on read-only files
* For C: just right
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* July 1987 CCKim Created.
*
*/
#ifndef NOLOCKF
/* on convex, lockf requires fcntl.h */
# ifndef LOCKFUSESFCNTL
# include <unistd.h>
/* unistd defines these unnecessarily (and problematically) */
# ifdef ultrix
# undef R_OK
# undef W_OK
# undef X_OK
# undef F_OK
# endif
# ifdef pyr
# undef R_OK
# undef W_OK
# undef X_OK
# undef F_OK
# endif
# else
# include <fcntl.h>
# endif
#endif
#include <errno.h>
#include <sys/types.h>
#include <sys/file.h>
#include <netat/appletalk.h>
#include <netat/afp.h>
#include <netat/afpcmd.h>
#ifdef NOFLOCK
# ifndef NOLOCKF
# ifndef LOCKF_ONLY
# define LOCKF_ONLY
# endif
# endif
#endif
/*
* The following routines define Byte Range Locking
*
* The following system calls (that only exist on some machines) will
* do the right thing:
* lockf - system V routine
*
* For systems without lockf, etc., someone has to hack together
* some system daemon or kernel driver.
*
*/
#ifdef NOLOCKF
/* These are here for systems that can't do byte range lock */
OSByteRangeLock(fd, offset, length, unlockflag, startendflag, fpos)
int fd;
sdword offset, length;
int unlockflag, startendflag;
sdword *fpos;
{
#ifdef DEBUG
printf("OS Byte Range lock: unimplemented on this OS\n");
#endif
return(aeMiscErr);
}
OSErr
OSTestLock(fd, length)
int fd;
sdword length;
{
return(noErr);
}
#else
/*
* Institute a byte range lock on a file
*
* offset can be negative if startendflag = 1 and then denotes
* offset relative from end of fork
* length must be positive
* unlockflag is set if want unlock
*
* Unlike AFP Spec: multiple ranges may overlap and unlock thusly
* may return NoMoreLocks as an error.
*
*/
OSErr
OSByteRangeLock(fd, offset, length, flags, fpos)
int fd;
sdword offset, length;
byte flags;
sdword *fpos;
{
int pos;
int startendflag = (BRL_START & flags);
int unlockflag = (BRL_UNLOCK & flags);
extern int errno;
#ifdef DEBUG
printf("OSBRL: %slocking offset %ld, length %x (%ld), from %s\n",
unlockflag ? "un" : "", offset, length, length,
startendflag ? "end" : "start");
#endif
if (length < 0) /* can only be -1 */
length = 0; /* length zero means entire file! */
if ((pos = lseek(fd, (off_t)offset, (startendflag ? L_XTND : L_SET))) < 0) {
*fpos = -1; /* unknown */
return(aeParamErr);
}
*fpos = pos;
if (lockf(fd, unlockflag ? F_ULOCK : F_TLOCK, length) < 0) {
switch (errno) {
#ifdef EREMOTE
/* not sure if this is the best thing to do */
case EREMOTE:
return(noErr);
#endif
#ifdef notdef
return(aeRangeNotLocked);
return(aeRangeOverlap);
#endif
case EACCES:
case EAGAIN:
#ifdef EINTR
case EINTR:
#endif
return(aeLockErr);
#ifdef EBADF
case EBADF: /* SunOS */
#endif
/* really permission denied (or, unlikely: bad file) */
#ifdef ENOLCK /* sunos */
case ENOLCK:
#endif
#ifdef EDEADLK
case EDEADLK:
#endif
return(aeNoMoreLocks);
default:
return(aeParamErr);
}
}
return(noErr);
}
/*
* returns noErr if the range starting at the current file position
* for length "length" is not locked.
*
*/
OSErr
OSTestLock(fd, length)
int fd;
sdword length;
{
extern int errno;
if (lockf(fd, F_TEST, length) < 0) {
#ifdef EREMOTE
if (errno == EREMOTE)
return(noErr);
#endif
#ifdef DEBUG
printf("File is locked\n");
#endif
return(aeLockErr);
}
return(noErr);
}
#endif
/*
* The following calls are used to coordinate read/writes for various
* files used by aufs.
*
* The basic primatives are:
* Lock File for Read - lock a file for reading (others may do the
* same). Do it if no write locks are in effect.
* Lock File for Write - lock a file for writing (other may not at the
* same time). Do it if no read or write locks are in effect.
* Unlock file
*
* Note, lffr is essentially a shared lock while lffw is an exclusive
* lock.
*
* Since most unix systems only issue advisory locks, the deal is that
* you call the routines before you do any reading or writing - this
* should be sufficient.
* Note: the lock calls are assumed to block - routines must be "good"
* about unlocking or things will break in a big way.
*
* Implementations:
* flock - implements shared and exclusive locks: perfect
* lockf - implements exclusive locks only (and only on writable fds):
* okay, but reads can get "out of date" or "bad" data
*
*
*/
boolean
OSLockFileforRead(fd)
int fd;
{
#ifndef NOFLOCK
if (flock(fd, LOCK_SH) < 0)
return(FALSE); /* problem!!! */
#else
# ifdef LOCKF_ONLY
if (lockf(fd, F_LOCK, 0) < 0) {
# ifdef EREMOTE
if (errno == EREMOTE)
return(TRUE);
# endif
if (errno == EBADF) /* file is open read-only */
return(TRUE); /* can't do lock, so let it go on */
return(FALSE);
}
# endif
#endif
return(TRUE);
}
boolean
OSLockFileforWrite(fd)
{
#ifndef NOFLOCK
if (flock(fd, LOCK_EX) < 0)
return(FALSE); /* problem!!! */
#else
# ifdef LOCKF_ONLY
if (lockf(fd, F_LOCK, 0) < 0) {
# ifdef EREMOTE
if (errno == EREMOTE)
return(TRUE);
# endif /* EREMOTE */
return(FALSE);
}
# endif /* LOCKF ONLY */
#endif
return(TRUE);
}
/*
* This implements an exclusive lock on the file. It differs from
* OSLockFileforRead in that it doesn't block
*
*/
#ifdef notdef /* not used */
boolean
OSMaybeLockFile(fd)
{
#ifndef NOFLOCK
if (flock(fd, LOCK_EX|LOCK_NB) < 0)
return(FALSE); /* problem!!! */
# else
# ifdef LOCKF_ONLY
if (lockf(fd, F_TLOCK, 0) < 0) {
# ifdef EREMOTE
if (errno == EREMOTE)
return(TRUE);
# endif
return(FALSE);
}
# endif
#endif
return(true);
}
#endif
boolean
OSUnlockFile(fd)
{
#ifndef NOFLOCK
if (flock(fd, LOCK_UN) < 0)
return(FALSE);
#else /* NOFLOCK */
# ifdef LOCKF_ONLY
if (lockf(fd, F_ULOCK, 0) < 0) {
# ifdef EREMOTE
if (errno == EREMOTE)
return(TRUE);
# endif /* EREMOTE */
return(FALSE);
}
# endif /* LOCKF_ONLY */
#endif /* end else NOFLOCK */
return(TRUE);
}
getlockinfo(haveflock,havelockf)
int *haveflock;
int *havelockf;
{
#ifdef NOFLOCK
*haveflock = 0;
#else
*haveflock = 1;
#endif
#ifdef NOLOCKF
*havelockf = 0;
#else
*havelockf = 1;
#endif
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.