/*
- * $Id: fork.c,v 1.43 2003-01-12 14:40:01 didg Exp $
+ * $Id: fork.c,v 1.44 2003-01-16 20:06:33 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include "desktop.h"
#include "volume.h"
-#define BYTELOCK_MAX 0x7FFFFFFFU
-#define BYTELOCK_MAXL 0x7FFFFFFFFFFFFFFFULL
-
struct ofork *writtenfork;
extern int getmetadata(struct vol *vol,
u_int16_t bitmap,
return getmetadata(vol, bitmap, ofork->of_name, dir, &st, buf, buflen, adp, attrbits );
}
+/* ---------------------------- */
+static off_t get_off_t(ibuf, is64)
+char **ibuf;
+int is64;
+{
+ u_int32_t temp;
+ off_t ret;
+
+ ret = 0;
+ memcpy(&temp, *ibuf, sizeof( temp ));
+ ret = ntohl(temp); /* ntohl is unsigned */
+ *ibuf += sizeof(temp);
+
+ if (is64) {
+ memcpy(&temp, *ibuf, sizeof( temp ));
+ *ibuf += sizeof(temp);
+ ret = ntohl(temp)| (ret << 32);
+ }
+ else {
+ ret = (int)ret; /* sign extend */
+ }
+ return ret;
+}
+
+/* ---------------------- */
+static int set_off_t(offset, rbuf, is64)
+off_t offset;
+char *rbuf;
+int is64;
+{
+ u_int32_t temp;
+ int ret;
+
+ ret = 0;
+ if (is64) {
+ temp = htonl(offset >> 32);
+ memcpy(rbuf, &temp, sizeof( temp ));
+ rbuf += sizeof(temp);
+ ret = sizeof( temp );
+ offset &= 0xffffffff;
+ }
+ temp = htonl(offset);
+ memcpy(rbuf, &temp, sizeof( temp ));
+ ret += sizeof( temp );
+
+ return ret;
+}
+
+/* ------------------------
+*/
+static int is_neg(int is64, off_t val)
+{
+ if (val < 0 || (sizeof(off_t) == 8 && !is64 && (val & 0x80000000U)))
+ return 1;
+ return 0;
+}
+
+static __inline__ int sum_neg(int is64, off_t offset, off_t reqcount)
+{
+ if (is_neg(is64, offset +reqcount) )
+ return 1;
+ return 0;
+}
+
/* -------------------------
*/
-#define SHARE 0
-#define EXCL 1
-static int setforkmode(struct adouble *adp, int eid, int ofrefnum, int what, int mode)
+static int setforkmode(struct adouble *adp, int eid, int ofrefnum, int what)
{
- int lockmode;
- int lockop;
-
- /* NOTE: we can't write lock a read-only file. on those, we just
- * make sure that we have a read lock set. that way, we at least prevent
- * someone else from really setting a deny read/write on the file.
- */
- lockmode = (ad_getoflags(adp, eid) & O_RDWR) ?ADLOCK_WR : ADLOCK_RD;
- lockop = (mode == EXCL)?lockmode:ADLOCK_RD;
-
- return ad_lock(adp, eid, lockop | ADLOCK_FILELOCK | ADLOCK_UPGRADE,
- what, 1, ofrefnum);
+ return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, what, 1, ofrefnum);
}
/* -------------------------
int mode;
if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
- return setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_NONE, SHARE);
+ return setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_NONE);
}
if ((access & (OPENACC_RD | OPENACC_DRD))) {
/* boolean logic is not enough, because getforkmode is not always telling the
* true
*/
- mode = ((access & OPENACC_DRD))?EXCL: SHARE;
if ((access & OPENACC_RD)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_RD, mode);
+ ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_RD);
if (ret)
return ret;
}
if ((access & OPENACC_DRD)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_RD, SHARE);
+ ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_RD);
if (ret)
return ret;
}
errno = EACCES;
return -1;
}
- mode = ((access & OPENACC_DWR))?EXCL: SHARE;
if ((access & OPENACC_WR)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_WR, mode);
+ ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_WR);
if (ret)
return ret;
}
if ((access & OPENACC_DWR)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_WR, SHARE);
+ ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_WR);
if (ret)
return ret;
}
int ibuflen, *rbuflen;
{
struct ofork *ofork;
- int32_t size;
+ off_t size;
u_int16_t ofrefnum, bitmap;
int err;
-
+ int is64;
+ int eid;
+ off_t st_size;
+
ibuf += 2;
+
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
ibuf += sizeof( ofrefnum );
+
memcpy(&bitmap, ibuf, sizeof(bitmap));
bitmap = ntohs(bitmap);
ibuf += sizeof( bitmap );
- memcpy(&size, ibuf, sizeof( size ));
- size = ntohl( size );
*rbuflen = 0;
- if (( ofork = of_find( ofrefnum )) == NULL ) {
+ if (NULL == ( ofork = of_find( ofrefnum )) ) {
LOG(log_error, logtype_afpd, "afp_setforkparams: of_find could not locate open fork refnum: %u", ofrefnum );
return( AFPERR_PARAM );
}
if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
return AFPERR_ACCESS;
- if (size < 0)
+ if ( ofork->of_flags & AFPFORK_DATA) {
+ eid = ADEID_DFORK;
+ } else if (ofork->of_flags & AFPFORK_RSRC) {
+ eid = ADEID_RFORK;
+ } else
return AFPERR_PARAM;
- if ((bitmap == (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_DATA)) {
+ if ( ( (bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) ))
+ && eid == ADEID_RFORK
+ ) ||
+ ( (bitmap & ( (1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN) ))
+ && eid == ADEID_DFORK)) {
+ return AFPERR_BITMAP;
+ }
+
+ is64 = 0;
+ if ((bitmap & ( (1<<FILPBIT_EXTDFLEN) | (1<<FILPBIT_EXTRFLEN) ))) {
+ if (afp_version >= 30) {
+ is64 = 4;
+ }
+ else
+ return AFPERR_BITMAP;
+ }
+
+ if (ibuflen < 2+ sizeof(ofrefnum) + sizeof(bitmap) + is64 +4)
+ return AFPERR_PARAM ;
+
+ size = get_off_t(&ibuf, is64);
+
+ if (size < 0)
+ return AFPERR_PARAM; /* Some MacOS don't return an error they just don't change the size! */
+
+
+ if (bitmap == (1<<FILPBIT_DFLEN) || bitmap == (1<<FILPBIT_EXTDFLEN)) {
+ st_size = ad_size(ofork->of_ad, eid);
+ err = -2;
+ if (st_size > size &&
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0)
+ goto afp_setfork_err;
+
err = ad_dtruncate( ofork->of_ad, size );
+ if (st_size > size)
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
if (err < 0)
goto afp_setfork_err;
- } else if ((bitmap == (1<<FILPBIT_RFLEN)) &&
- (ofork->of_flags & AFPFORK_RSRC)) {
+ } else if (bitmap == (1<<FILPBIT_RFLEN) || bitmap == (1<<FILPBIT_EXTRFLEN)) {
ad_refresh( ofork->of_ad );
+
+ st_size = ad_size(ofork->of_ad, eid);
+ err = -2;
+ if (st_size > size &&
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) {
+ goto afp_setfork_err;
+ }
err = ad_rtruncate(ofork->of_ad, size);
+ if (st_size > size)
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
if (err < 0)
goto afp_setfork_err;
if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
- LOG(log_error, logtype_afpd, "afp_setforkparams: ad_flush: %s",
- strerror(errno) );
- return( AFPERR_PARAM );
+ LOG(log_error, logtype_afpd, "afp_setforkparams: ad_flush: %s",strerror(errno) );
+ return AFPERR_PARAM;
}
} else
return AFPERR_BITMAP;
#define ENDBIT(a) ((a) & 0x80)
#define UNLOCKBIT(a) ((a) & 0x01)
-static off_t get_off_t(ibuf, is64)
-char **ibuf;
-int is64;
-{
- u_int32_t temp;
- off_t ret;
-
- memcpy(&temp, *ibuf, sizeof( temp ));
- ret = ntohl(temp); /* ntohl is unsigned */
- *ibuf += sizeof(temp);
-
- if (is64) {
- memcpy(&temp, *ibuf, sizeof( temp ));
- *ibuf += sizeof(temp);
- ret = ntohl(temp)| (ret << 32);
- }
- return ret;
-}
-
-/* ---------------------- */
-static int set_off_t(offset, rbuf, is64)
-off_t offset;
-char *rbuf;
-int is64;
-{
- u_int32_t temp;
- int ret;
-
- ret = 0;
- if (is64) {
- temp = htonl(offset >> 32);
- memcpy(rbuf, &temp, sizeof( temp ));
- rbuf += sizeof(temp);
- ret = sizeof( temp );
- offset &= 0xffffffff;
- }
- temp = htonl(offset);
- memcpy(rbuf, &temp, sizeof( temp ));
- ret += sizeof( temp );
-
- return ret;
-}
/* ---------------------- */
static int byte_lock(obj, ibuf, ibuflen, rbuf, rbuflen, is64 )
int eid;
u_int16_t ofrefnum;
u_int8_t flags;
-
+ int lockop;
+
*rbuflen = 0;
/* figure out parameters */
memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
ibuf += sizeof(ofrefnum);
- if (( ofork = of_find( ofrefnum )) == NULL ) {
+ if (NULL == ( ofork = of_find( ofrefnum )) ) {
LOG(log_error, logtype_afpd, "afp_bytelock: of_find");
return( AFPERR_PARAM );
}
offset = get_off_t(&ibuf, is64);
length = get_off_t(&ibuf, is64);
- if (is64) {
- if (length == -1)
- length = BYTELOCK_MAXL;
- else if (length <= 0) {
- return AFPERR_PARAM;
- } else if ((length >= AD_FILELOCK_BASE) &&
- (ad_hfileno(ofork->of_ad) == -1)) {
- return AFPERR_LOCK;
- }
- }
- else {
- if (length == 0xFFFFFFFF)
- length = BYTELOCK_MAX;
- else if (!length || (length & (1 << 31))) {
- return AFPERR_PARAM;
- } else if ((length >= AD_FILELOCK_BASE) &&
- (ad_hfileno(ofork->of_ad) == -1)) {
- return AFPERR_LOCK;
- }
+ /* FIXME AD_FILELOCK test is surely wrong */
+ if (length == -1)
+ length = BYTELOCK_MAX;
+ else if (!length || is_neg(is64, length)) {
+ return AFPERR_PARAM;
+ } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_hfileno(ofork->of_ad))) {
+ return AFPERR_LOCK;
}
-
- if (ENDBIT(flags))
- offset += ad_size(ofork->of_ad, eid);
+ if (ENDBIT(flags)) {
+ offset += ad_size(ofork->of_ad, eid);
+ /* FIXME what do we do if file size > 2 GB and
+ it's not byte_lock_ext?
+ */
+ }
if (offset < 0) /* error if we have a negative offset */
return AFPERR_PARAM;
/* if the file is a read-only file, we use read locks instead of
* write locks. that way, we can prevent anyone from initiating
* a write lock. */
- if (ad_lock(ofork->of_ad, eid, UNLOCKBIT(flags) ? ADLOCK_CLR :
- ((ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
- ADLOCK_WR : ADLOCK_RD), offset, length,
+ lockop = UNLOCKBIT(flags) ? ADLOCK_CLR : ADLOCK_WR;
+ if (ad_lock(ofork->of_ad, eid, lockop, offset, length,
ofork->of_refnum) < 0) {
switch (errno) {
case EACCES:
static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
- int offset, u_char nlmask,
+ off_t offset, u_char nlmask,
u_char nlchar, char *rbuf,
int *rbuflen, const int xlate)
{
savereqcount = reqcount;
saveoff = offset;
- if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount) < 0) {
+ if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount,ofork->of_refnum) < 0) {
err = AFPERR_LOCK;
goto afp_read_err;
}
afp_read_exit:
LOG(log_error, logtype_afpd, "afp_read: %s", strerror(errno));
dsi_readdone(dsi);
- ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
obj->exit(1);
}
afp_read_done:
- ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
return err;
afp_read_err:
ibuf += 2;
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
- if (( ofork = of_find( ofrefnum )) == NULL ) {
+ if (NULL == ( ofork = of_find( ofrefnum )) ) {
LOG(log_error, logtype_afpd, "afp_flushfork: of_find");
return( AFPERR_PARAM );
}
ibuf += 2;
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
- if (( ofork = of_find( ofrefnum )) == NULL ) {
+ if (NULL == ( ofork = of_find( ofrefnum )) ) {
LOG(log_error, logtype_afpd, "afp_closefork: of_find");
return( AFPERR_PARAM );
}
return cc;
}
+
/* FPWrite. NOTE: on an error, we always use afp_write_err as
* the client may have sent us a bunch of data that's not reflected
* in reqcount et al. */
offset = get_off_t(&ibuf, is64);
reqcount = get_off_t(&ibuf, is64);
- if (( ofork = of_find( ofrefnum )) == NULL ) {
+ if (NULL == ( ofork = of_find( ofrefnum )) ) {
LOG(log_error, logtype_afpd, "afp_write: of_find");
err = AFPERR_PARAM;
goto afp_write_err;
/* offset can overflow on 64-bit capable filesystems.
* report disk full if that's going to happen. */
- if (offset + reqcount < 0) {
+ if (sum_neg(is64, offset, reqcount)) {
err = AFPERR_DFULL;
goto afp_write_err;
}
saveoff = offset;
if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
- reqcount) < 0) {
+ reqcount, ofork->of_refnum) < 0) {
err = AFPERR_LOCK;
goto afp_write_err;
}
if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
xlate)) < 0) {
*rbuflen = 0;
- ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
return cc;
}
offset += cc;
(cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
dsi_writeflush(dsi);
*rbuflen = 0;
- ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
return cc;
}
offset += cc;
dsi_writeflush(dsi);
*rbuflen = 0;
ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
- reqcount);
+ reqcount, ofork->of_refnum);
return cc;
}
dsi_writeflush(dsi);
*rbuflen = 0;
ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
- reqcount);
+ reqcount, ofork->of_refnum);
return cc;
}
offset += cc;
break;
}
- ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
if ( ad_hfileno( ofork->of_ad ) != -1 )
ofork->of_flags |= AFPFORK_DIRTY;
ibuf += sizeof( bitmap );
*rbuflen = 0;
- if (( ofork = of_find( ofrefnum )) == NULL ) {
+ if (NULL == ( ofork = of_find( ofrefnum )) ) {
LOG(log_error, logtype_afpd, "afp_getforkparams: of_find");
return( AFPERR_PARAM );
}
/*
- * $Id: ad_lock.c,v 1.6 2002-11-14 17:15:22 srittau Exp $
+ * $Id: ad_lock.c,v 1.7 2003-01-16 20:06:33 didg Exp $
*
* Copyright (c) 1998,1999 Adrian Sun (asun@zoology.washington.edu)
* All Rights Reserved. See COPYRIGHT for more information.
((type) == ADLOCK_WR ? LOCK_EX : \
((type) == ADLOCK_CLR ? LOCK_UN : -1)))
-#define XLATE_FCNTL_LOCK(type) ((type) == ADLOCK_RD ? F_RDLCK : \
-((type) == ADLOCK_WR ? F_WRLCK : \
- ((type) == ADLOCK_CLR ? F_UNLCK : -1)))
-
-#define OVERLAP(a,alen,b,blen) ((!(alen) && (a) <= (b)) || \
- (!(blen) && (b) <= (a)) || \
- ((((a) + (alen)) > (b)) && \
- (((b) + (blen)) > (a))))
+/* ----------------------- */
+static int XLATE_FCNTL_LOCK(int type)
+{
+ switch(type) {
+ case ADLOCK_RD:
+ return F_RDLCK;
+ case ADLOCK_WR:
+ return F_WRLCK;
+ case ADLOCK_CLR:
+ return F_UNLCK;
+ }
+ return -1;
+}
+
+/* ----------------------- */
+
+static int OVERLAP(off_t a, off_t alen, off_t b, off_t blen)
+{
+ return (!alen && a <= b) ||
+ (!blen && b <= a) ||
+ ( (a + alen > b) && (b + blen > a) );
+}
/* allocation for lock regions. we allocate aggressively and shrink
/* relock any byte lock that overlaps off/len. unlock everything
* else. */
static __inline__ void adf_relockrange(struct ad_fd *ad, int fd,
- const off_t off, const size_t len)
+ const off_t off, const off_t len)
{
adf_lock_t *lock = ad->adf_lock;
int i;
static __inline__ int adf_findlock(struct ad_fd *ad,
const int user, const int type,
const off_t off,
- const size_t len)
+ const off_t len)
{
adf_lock_t *lock = ad->adf_lock;
int i;
static __inline__ int adf_findxlock(struct ad_fd *ad,
const int user, const int type,
const off_t off,
- const size_t len)
+ const off_t len)
{
adf_lock_t *lock = ad->adf_lock;
int i;
return start;
}
-int ad_fcntl_lock(struct adouble *ad, const u_int32_t eid, const int type,
- const off_t off, const size_t len, const int user)
+/* ------------------ */
+int ad_fcntl_lock(struct adouble *ad, const u_int32_t eid, const int locktype,
+ const off_t off, const off_t len, const int user)
{
struct flock lock;
struct ad_fd *adf;
adf_lock_t *adflock, *oldlock;
int i;
-
+ int type;
+
lock.l_start = off;
+ type = locktype;
if (eid == ADEID_DFORK) {
adf = &ad->ad_df;
if ((type & ADLOCK_FILELOCK)) {
if (ad_hfileno(ad) != -1) {
- lock.l_start = df2off(off);
+ lock.l_start = df2off(off);
adf = &ad->ad_hf;
}
}
else
lock.l_start += ad_getentryoff(ad, eid);
}
-
+ /* NOTE: we can't write lock a read-only file. on those, we just
+ * make sure that we have a read lock set. that way, we at least prevent
+ * someone else from really setting a deny read/write on the file.
+ */
+ if (!(adf->adf_flags & O_RDWR) && (type & ADLOCK_WR)) {
+ type = (type & ~ADLOCK_WR) | ADLOCK_RD;
+ }
+
lock.l_type = XLATE_FCNTL_LOCK(type & ADLOCK_MASK);
+ lock.l_whence = SEEK_SET;
+ lock.l_len = len;
+
+ /* byte_lock(len=-1) lock whole file */
+ if (len == BYTELOCK_MAX) {
+ lock.l_len -= lock.l_start; /* otherwise EOVERFLOW error */
+ }
/* see if it's locked by another user.
* NOTE: this guarantees that any existing locks must be at most
* guaranteed to be ORable. */
if (adf_findxlock(adf, user, ADLOCK_WR |
((type & ADLOCK_WR) ? ADLOCK_RD : 0),
- lock.l_start, len) > -1) {
+ lock.l_start, lock.l_len) > -1) {
errno = EACCES;
return -1;
}
/* look for any existing lock that we may have */
- i = adf_findlock(adf, user, ADLOCK_RD | ADLOCK_WR, lock.l_start, len);
+ i = adf_findlock(adf, user, ADLOCK_RD | ADLOCK_WR, lock.l_start, lock.l_len);
adflock = (i < 0) ? NULL : adf->adf_lock + i;
/* here's what we check for:
if ((!adflock && (lock.l_type == F_UNLCK)) ||
(adflock && !(type & ADLOCK_UPGRADE) &&
((lock.l_type != F_UNLCK) || (adflock->lock.l_start != lock.l_start) ||
- (adflock->lock.l_len != len)))) {
+ (adflock->lock.l_len != lock.l_len)))) {
errno = EINVAL;
return -1;
}
- lock.l_whence = SEEK_SET;
- lock.l_len = len;
/* now, update our list of locks */
/* clear the lock */
/* it wasn't an upgrade */
oldlock = NULL;
- if ((lock.l_type = F_RDLCK) &&
- ((i = adf_findxlock(adf, user, ADLOCK_RD, lock.l_start, len)) > -1)) {
+ if ((lock.l_type == F_RDLCK) &&
+ ((i = adf_findxlock(adf, user, ADLOCK_RD, lock.l_start, lock.l_len)) > -1)) {
oldlock = adf->adf_lock + i;
}
/* Does another process have a lock?
FIXME F_GETLK ?
*/
- lock.l_type = (ad_getoflags(ad, eid) & O_RDWR) ?F_WRLCK : F_RDLCK;
+ lock.l_type = (adf->adf_flags & O_RDWR) ?F_WRLCK : F_RDLCK;
if (fcntl(adf->adf_fd, F_SETLK, &lock) < 0) {
return (errno == EACCES || errno == EAGAIN)?1:-1;
/* -------------------------
*/
-/* with temp locks, we don't need to distinguish within the same
- * process as everything is single-threaded. in addition, if
- * multi-threading gets added, it will only be in a few areas. */
int ad_fcntl_tmplock(struct adouble *ad, const u_int32_t eid, const int type,
- const off_t off, const size_t len)
+ const off_t off, const off_t len, const int user)
{
struct flock lock;
struct ad_fd *adf;
lock.l_whence = SEEK_SET;
lock.l_len = len;
+ /* see if it's locked by another user. */
+ if (user && adf_findxlock(adf, user, ADLOCK_WR |
+ ((type & ADLOCK_WR) ? ADLOCK_RD : 0),
+ lock.l_start, lock.l_len) > -1) {
+ errno = EACCES;
+ return -1;
+ }
+
/* okay, we might have ranges byte-locked. we need to make sure that
* we restore the appropriate ranges once we're done. so, we check
* for overlap on an unlock and relock.