ftp.nice.ch/pub/next/unix/network/system/cap.5.0.s.tar.gz#/cap_5.0/lib/afp/afposlock.c

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.