home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR41
/
CBASE11.ZIP
/
LOCKB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-01
|
8KB
|
340 lines
/*
* Copyright (c) 1989-1992 Citadel Software, Inc.
* All Rights Reserved
*/
/* #ident "@(#)lockb.c 1.7 - 93/01/01" */
#include <port.h>
/* standard headers */
#include <errno.h>
#ifdef AC_STDDEF
#include <stddef.h>
#endif
/* local headers */
#include "blkio_.h"
/* system headers */
#if OPSYS == OS_AMIGA /* Amiga DOS =================================*/
#elif OPSYS == OS_MAC /* Macintosh =================================*/
#elif OPSYS == OS_DOS /* DOS =======================================*/
#include <limits.h> /* LONG_MAX definition */
#if CCOM == CC_BC /* Borland C++ -------------------------------*/
#include <io.h>
#define _LK_UNLCK (0) /* unlock */
#define _LK_LOCK (1) /* lock */
#define _LK_NBLCK (2) /* non-blocking lock */
#define _LK_RLCK (3) /* read lock */
#define _LK_NBRLCK (4) /* non-blocking read lock */
#elif CCOM == CC_MSC || CCOM == CC_MSQC /* Microsoft C or Quick C ------------*/
#include <sys\locking.h>
#include <io.h>
#endif
#elif OPSYS == OS_UNIX /* UNIX ======================================*/
#include <fcntl.h>
#ifdef AC_PROTO
int fcntl(int fd, int cmd, ...);
#else
int fcntl();
#endif
#elif OPSYS == OS_VMS /* VMS =======================================*/
#endif
/*man---------------------------------------------------------------------------
NAME
lockb - block file record locking
SYNOPSIS
#include <blkio.h>
int lockb(bp, ltype, start, len)
BLKFILE *bp;
int ltype;
bpos_t start;
bpos_t len;
DESCRIPTION
The lockb function will allow segments of a block file to be
locked. bp is the BLKFILE pointer for the file to be locked.
ltype indicates the target status of the lock. The lock types
available are:
B_UNLCK unlock block file segment
B_RDLCK lock block file segment for reading
B_WRLCK lock block file segment for reading and writing
B_RDLKW lock block file segment for reading (wait)
B_WRLKW lock block file segment for reading and writing (wait)
For the lock types which wait, lockb will not return until the
lock is available. For the lock types which do not wait, if the
lock is unavailable because of a lock held by another process a
value of -1 is returned and errno set to EAGAIN.
start is the first block to lock. len is the number of
contiguous blocks including and following block start to be
locked or unlocked. A lock may be set to extend to the end of
the file by setting len to zero.
The buffers are flushed before unlocking.
lockb will fail if one or more of the following is true:
[EAGAIN] ltype is B_RDLCK and the file segment to be locked
is already write locked by another process, or
ltype is B_WRLCK and the file segment to be locked
is already read or write locked by another
process.
[EINVAL] bp is is not a valid BLKFILE pointer.
[EINVAL] ltype is not one of the valid lock types.
[BENOPEN] bp is not open.
[BENOPEN] ltype is B_RDLCK or B_RDLKW and bp is not opened
for reading or ltype is B_WRLCK or B_WRLKW and bp
is not open for writing.
DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise,
a value of -1 is returned, and errno set to indicate the error.
------------------------------------------------------------------------------*/
#ifdef AC_PROTO
int lockb(BLKFILE *bp, int ltype, bpos_t start, bpos_t len)
#else
int lockb(bp, ltype, start, len)
BLKFILE *bp;
int ltype;
bpos_t start;
bpos_t len;
#endif
{
#if OPSYS == AMIGA
#elif OPSYS == OS_DOS
long length = 0; /* length in bytes of segment to lock */
int mode = 0; /* file locking mode */
long offset = 0; /* offset from start of file */
#elif OPSYS == OS_MAC
#elif OPSYS == OS_UNIX
int cmd = 0; /* lock command */
struct flock lck; /* lock structure */
#elif OPSYS == OS_VMS
#endif
/* validate arguments */
if (!b_valid(bp)) {
errno = EINVAL;
return -1;
}
/* check if not open */
if (!(bp->flags & BIOOPEN)) {
errno = BENOPEN;
return -1;
}
/* set lock flags */
switch (ltype) {
case B_RDLCK:
if (!(bp->flags & BIOREAD)) {
errno = BENOPEN;
return -1;
}
#if OPSYS == AMIGA
#elif OPSYS == OS_DOS
mode = _LK_NBRLCK;
#elif OPSYS == OS_MAC
#elif OPSYS == OS_UNIX
cmd = F_SETLK;
lck.l_type = F_RDLCK;
#elif OPSYS == OS_VMS
#endif
break;
case B_RDLKW:
if (!(bp->flags & BIOREAD)) {
errno = BENOPEN;
return -1;
}
#if OPSYS == AMIGA
#elif OPSYS == OS_DOS
mode = _LK_RLCK;
#elif OPSYS == OS_MAC
#elif OPSYS == OS_UNIX
cmd = F_SETLKW;
lck.l_type = F_RDLCK;
#elif OPSYS == OS_VMS
#endif
break;
case B_WRLCK:
if (!(bp->flags & BIOWRITE)) {
errno = BENOPEN;
return -1;
}
#if OPSYS == AMIGA
#elif OPSYS == OS_DOS
mode = _LK_NBLCK;
#elif OPSYS == OS_MAC
#elif OPSYS == OS_UNIX
cmd = F_SETLK;
lck.l_type = F_WRLCK;
#elif OPSYS == OS_VMS
#endif
break;
case B_WRLKW:
if (!(bp->flags & BIOWRITE)) {
errno = BENOPEN;
return -1;
}
#if OPSYS == AMIGA
#elif OPSYS == OS_DOS
mode = _LK_LOCK;
#elif OPSYS == OS_MAC
#elif OPSYS == OS_UNIX
cmd = F_SETLKW;
lck.l_type = F_WRLCK;
#elif OPSYS == OS_VMS
#endif
break;
case B_UNLCK:
/* flush buffers */
if (bflush(bp) == -1) {
BERRLOG;
return -1;
}
#if OPSYS == AMIGA
#elif OPSYS == OS_DOS
mode = _LK_UNLCK;
#elif OPSYS == OS_MAC
#elif OPSYS == OS_UNIX
cmd = F_SETLK;
lck.l_type = F_UNLCK;
#elif OPSYS == OS_VMS
#endif
break;
default:
errno = EINVAL;
return -1;
break;
}
/* lock */
#ifndef SINGLE_USER
#if OPSYS == AMIGA
#elif OPSYS == OS_DOS
if (start == 0) {
offset = 0;
if (len == 0) {
length = LONG_MAX;
} else {
length = bp->hdrsize + (len - 1) * bp->blksize;
}
} else {
offset = bp->hdrsize + (start - 1) * bp->blksize;
if (len == 0) {
length = LONG_MAX - offset;
} else {
length = len * bp->blksize;
}
}
#if CCOM == CC_BC
switch (mode) {
case _LK_UNLCK: /* unlock */
if (unlock(bp->fd.i, offset, length) == -1) {
/* ignore 'segment not locked' error */
if (errno == EACCES) return 0;
return -1;
}
break;
default: /* lock */
if (lock(bp->fd.i, offset, length) == -1) {
if (errno == EACCES) errno = EAGAIN;
#ifdef DEBUG
if (errno != EAGAIN) BERRLOG;
#endif
return -1;
}
break;
}
#elif CCOM == CC_MSC || CCOM == CC_MSQC
if (lseek(bp->fd.i, offset, SEEK_SET) == -1) {
BERRLOG;
return -1;
}
if (_locking(bp->fd.i, mode, length) == -1) {
/* ignore 'segment not locked' error */
if (mode == _LK_UNLCK) {
if (errno == EACCES) return 0;
}
if (errno == EACCES) errno = EAGAIN;
#ifdef DEBUG
if (errno != EAGAIN) BERRLOG;
#endif
return -1;
}
#endif
#elif OPSYS == OS_MAC
#elif OPSYS == OS_UNIX
if (start == 0) {
lck.l_whence = 0;
if (len == 0) {
lck.l_len = 0;
} else {
lck.l_len = bp->hdrsize + (len - 1) * bp->blksize;
}
} else {
lck.l_whence = bp->hdrsize + (start - 1) * bp->blksize;
if (len == 0) {
lck.l_len = 0;
} else {
lck.l_len = len * bp->blksize;
}
}
lck.l_start = 0;
/* lck.l_sysid = 0; l_sysid not defined by BSD UNIX */
lck.l_pid = 0;
if (fcntl(bp->fd.i, cmd, &lck) == -1) {
/* new versions of fcntl will use EAGAIN */
if (errno == EACCES) errno = EAGAIN;
#ifdef DEBUG
if (errno != EAGAIN) BERRLOG;
#endif
return -1;
}
#elif OPSYS == OS_VMS
#endif
#endif /* #ifndef SINGLE_USER */
/* if locking, load endblk */
if (ltype != B_UNLCK) {
if (b_uendblk(bp, &bp->endblk) == -1) {
BERRLOG;
return -1;
}
}
return 0;
}