diff --git a/src/xpdev/filewrap.c b/src/xpdev/filewrap.c index 810271f990226dae3076a7c2b9931b1a3b778f5c..acaaa37c49478080e440f15d9304ea276ce32c11 100644 --- a/src/xpdev/filewrap.c +++ b/src/xpdev/filewrap.c @@ -83,9 +83,11 @@ long DLLCALL filelength(int fd) /* Sets a lock on a portion of a file */ int DLLCALL lock(int fd, long pos, int len) { - int flags; +#if defined(F_SANERDLCKNO) || !defined(BSD) struct flock alock; +#ifndef F_SANEWRLCKNO + int flags; if((flags=fcntl(fd,F_GETFL))==-1) return -1; @@ -93,16 +95,22 @@ int DLLCALL lock(int fd, long pos, int len) alock.l_type = F_RDLCK; /* set read lock to prevent writes */ else alock.l_type = F_WRLCK; /* set write lock to prevent all access */ +#else + alock.l_type = F_SANEWRLCKNO; +#endif alock.l_whence = L_SET; /* SEEK_SET */ alock.l_start = pos; alock.l_len = len; if(fcntl(fd, F_SETLK, &alock)==-1) return(-1); +#endif +#ifndef F_SANEWRLCKNO /* use flock (doesn't work over NFS) */ if(flock(fd,LOCK_EX|LOCK_NB)!=0) return(-1); +#endif return(0); } @@ -110,18 +118,26 @@ int DLLCALL lock(int fd, long pos, int len) /* Removes a lock from a file record */ int DLLCALL unlock(int fd, long pos, int len) { - struct flock alock; +#if defined(F_SANEUNLCK) || !defined(BSD) + struct flock alock; +#ifdef F_SANEUNLCK + alock.l_type = F_SANEUNLCK; /* remove the lock */ +#else alock.l_type = F_UNLCK; /* remove the lock */ +#endif alock.l_whence = L_SET; alock.l_start = pos; alock.l_len = len; if(fcntl(fd, F_SETLK, &alock)==-1) return(-1); +#endif +#ifndef F_SANEUNLCK /* use flock (doesn't work over NFS) */ if(flock(fd,LOCK_UN|LOCK_NB)!=0) return(-1); +#endif return(0); } @@ -130,7 +146,9 @@ int DLLCALL unlock(int fd, long pos, int len) int DLLCALL sopen(char *fn, int access, int share) { int fd; +#ifndef F_SANEWRLCKNO int flock_op=LOCK_NB; /* non-blocking */ +#endif struct flock alock; if ((fd = open(fn, access, S_IREAD|S_IWRITE)) < 0) @@ -139,6 +157,20 @@ int DLLCALL sopen(char *fn, int access, int share) if (share == SH_DENYNO) /* no lock needed */ return fd; +#if defined(F_SANEWRLCKNO) || !defined(BSD) + /* use fcntl (doesn't work correctly with threads) */ + alock.l_type = share; + alock.l_whence = L_SET; + alock.l_start = 0; + alock.l_len = 0; /* lock to EOF */ + + if(fcntl(fd, F_SETLK, &alock)==-1) { + close(fd); + return -1; + } +#endif + +#ifndef F_SANEWRLCKNO /* use flock (doesn't work over NFS) */ if(share==SH_DENYRW) flock_op|=LOCK_EX; @@ -150,17 +182,7 @@ int DLLCALL sopen(char *fn, int access, int share) close(fd); return(-1); } - - /* use fcntl (doesn't work correctly with threads) */ - alock.l_type = share; - alock.l_whence = L_SET; - alock.l_start = 0; - alock.l_len = 0; /* lock to EOF */ - - if(fcntl(fd, F_SETLK, &alock)==-1) { - close(fd); - return -1; - } +#endif return fd; } diff --git a/src/xpdev/filewrap.h b/src/xpdev/filewrap.h index 5df0310b293253c4670c8130fd5e1851245b11a4..f4f2aa42357979107911cad1b7f5ffffc483b54e 100644 --- a/src/xpdev/filewrap.h +++ b/src/xpdev/filewrap.h @@ -78,8 +78,17 @@ #define O_DENYNONE (1<<31) /* req'd for Baja/nopen compatibility */ #define SH_DENYNO 2 // no locks +#ifdef F_SANEWRLCKNO + #define SH_DENYRW F_SANEWRLCKNO // exclusive lock +#else #define SH_DENYRW F_WRLCK // exclusive lock +#endif + +#ifdef F_SANERDLCKNO + #define SH_DENYWR F_SANERDLCKNO // shareable lock +#else #define SH_DENYWR F_RDLCK // shareable lock +#endif #define chsize(fd,size) ftruncate(fd,size) #define tell(fd) lseek(fd,0,SEEK_CUR) diff --git a/src/xpdev/wraptest.c b/src/xpdev/wraptest.c index 2c72679179c6c6400c48422c6ec0a286b4cfb71e..58462c788ca176e93fdd7173e62bed0bdbf6ecad 100644 --- a/src/xpdev/wraptest.c +++ b/src/xpdev/wraptest.c @@ -46,6 +46,7 @@ int main() DIRENT* dirent; thread_data_t thread_data; int fd; + int fd2; /* Show platform details */ DESCRIBE_COMPILER(compiler); @@ -115,6 +116,21 @@ int main() printf("!FAILURE file locking\n"); else printf("SUCCESS! Record locking\n"); + if((fd2=sopen(LOCK_FNAME,O_RDWR,SH_DENYRW))!=-1) { + printf("SUCCESS! Cannot reopen SH_DENYRW while lock is held\n"); + close(fd2); + } + else { + printf("!FAILURE can reopen SH_DENYRW while lock is held\n"); + } + if(unlock(fd,LOCK_OFFSET,LOCK_LEN)) + printf("!FAILURE unlock() non-functional\n"); + if(lock(fd,LOCK_OFFSET+LOCK_LEN+1,LOCK_LEN)) + printf("SUCCESS! Cannot re-lock after non-overlapping unlock()\n"); + else + printf("!FAILURE can re-lock after non-overlappping unlock()\n"); + if(lock(fd,LOCK_OFFSET,LOCK_LEN)) + printf("!FAILURE cannot re-lock unlocked area\n"); close(fd); /* getch test */