/* f4lock.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */ #include "d4all.h" #ifdef S4IBMOS2 #define INCL_DOSFILEMGR #include #ifndef NO_ERROR #define NO_ERROR 0 #define ERROR_LOCK_VIOLATION 33 #define S4BYTE_DEFINED #endif #endif #ifdef __TURBOC__ #pragma hdrstop #endif #ifdef S4TEMP #include "t4test.h" #endif #ifndef S4SINGLE #ifndef S4WINTEL #ifdef S4LOCKF #include #else /* */ #include /* */ #endif #else #ifndef S4WIN32 #ifndef __TURBOC__ #ifndef S4IBMOS2 #include #define S4LOCKING #endif #endif #ifdef __ZTC__ extern int errno ; #endif #ifdef _MSC_VER #include #endif #ifdef __TURBOC__ #ifndef S4OS2 #ifdef __BORLANDC__ #include /* Borland C++ compilers */ #else #include /* Turbo C++ for DOS compilers */ /* #include */ /* Turbo C++ for Win compilers */ #endif /* extern int cdecl errno ; */ #endif #endif /* #include */ /* #include */ #endif #endif #endif #ifndef S4WIN32 /* #include */ #include #endif #ifdef S4ERRNO extern int errno ; #endif #ifndef S4SINGLE #ifdef S4CLIENT static char this4application[] = "THIS APPLICATION" ; int dfile4registerLocked( DATA4FILE *locker, const long lockId ) { CODE4 *c4 ; if ( locker == 0 ) return 0 ; c4 = locker->c4 ; c4->lockedLockItem = lockId ; c4->lockedFileName = locker->accessName ; c4->lockedUserId = this4application ; c4->lockedNetId = this4application ; return 0 ; } #else int dfile4registerLocked( DATA4FILE *d4, const long lockId, int doExtra ) { DATA4 *lockedData ; TRAN4 *trans ; CODE4 *c4 ; long clientId, serverId ; if ( d4 == 0 ) return 0 ; c4 = d4->c4 ; #ifdef E4PARM_LOW if ( lockId < -2L ) return error4( c4, e4parm, E96701 ) ; #endif #ifdef S4SERVER c4->server->lockedLockItem = lockId ; #else c4->lockedLockItem = lockId ; #endif if ( doExtra ) { switch( lockId ) { case -1: /* file */ clientId = d4->fileClientLock ; serverId = d4->fileServerLock ; break ; case 0: /* append lock */ clientId = d4->appendClientLock ; serverId = d4->appendServerLock ; if ( clientId == 0 || serverId == 0 ) /* probably due to a file lock */ { clientId = d4->fileClientLock ; serverId = d4->fileServerLock ; } break ; default: /* record number */ clientId = d4->tempClientLock ; serverId = d4->tempServerLock ; if ( clientId == 0 || serverId == 0 ) /* probably due to a file lock */ { clientId = d4->fileClientLock ; serverId = d4->fileServerLock ; } break ; } if ( clientId == 0 || serverId == 0 ) return 0 ; lockedData = code4idData( c4, serverId, clientId ) ; if ( lockedData == 0 ) return 0 ; trans = lockedData->trans ; #ifdef S4SERVER c4->server->lockedFileName = lockedData->alias ; c4->server->lockedUserId = trans->userId ; c4->server->lockedNetId = trans->netId ; #else c4->lockedFileName = lockedData->alias ; c4->lockedUserId = trans->userId ; c4->lockedNetId = trans->netId ; #endif } return 0 ; } #endif /* S4CLIENT */ #endif /* S4SINGLE */ #ifdef S4SERVER /* leave non-inlined in order to force const returns */ const char *S4FUNCTION code4lockNetworkId( CODE4 *c4 ) { return c4->server->lockedNetId ; } const char *S4FUNCTION code4lockUserId( CODE4 *c4 ) { return c4->server->lockedUserId ; } const char *S4FUNCTION code4lockFileName( CODE4 *c4 ) { return c4->server->lockedFileName ; } long S4FUNCTION code4lockItem( CODE4 *c4 ) { return c4->server->lockedLockItem ; } #else const char *S4FUNCTION code4lockNetworkId( CODE4 *c4 ) { #ifdef E4PARM_HIGH if ( c4 == 0 ) { error4( 0, e4parm_null, E91009 ) ; return 0 ; } #endif return c4->lockedNetId ; } const char *S4FUNCTION code4lockUserId( CODE4 *c4 ) { #ifdef E4PARM_HIGH if ( c4 == 0 ) { error4( 0, e4parm_null, E91010 ) ; return 0 ; } #endif return c4->lockedUserId ; } const char *S4FUNCTION code4lockFileName( CODE4 *c4 ) { #ifdef E4PARM_HIGH if ( c4 == 0 ) { error4( 0, e4parm_null, E91011 ) ; return 0 ; } #endif return c4->lockedFileName ; } long S4FUNCTION code4lockItem( CODE4 *c4 ) { #ifdef E4PARM_HIGH if ( c4 == 0 ) { error4( 0, e4parm_null, E91012 ) ; return 0 ; } #endif return c4->lockedLockItem ; } #endif #ifdef P4ARGS_USED #pragma argsused #endif int S4FUNCTION file4lock( FILE4 *file, const long posStart, const long numBytes ) { #ifdef S4SINGLE return 0 ; #else int rc, numAttempts ; CODE4 *c4 ; #ifdef S4MULTIC4 int pid, status; #endif #ifdef S4IBMOS2 struct LockStrc { long FileOffset ; long RangeLength ; } L4RANGE ; #endif /* */ /* */ /* */ #ifdef E4PARM_HIGH if ( file == 0 ) return error4( 0, e4parm_null, E90613 ) ; #ifndef S4MDX if ( numBytes < 0 || posStart < 0 ) return error4( 0, e4parm, E90613 ) ; #endif #endif if ( numBytes == 0 || file->isReadOnly || file->lowAccessMode != OPEN4DENY_NONE ) /* don't check error code */ return 0 ; #ifdef E4PARM_HIGH /* check before c4 since it will be invalid if file handle invalid */ if ( file->hand == -1 ) return error4( 0, e4parm, E80608 ) ; #endif c4 = file->codeBase ; if ( error4code( c4 ) < 0 ) return e4codeBase ; #ifdef S4LOCK_HOOK numAttempts = 0 ; #else numAttempts = c4->lockAttempts ; if ( numAttempts == 0 ) numAttempts = 1 ; #endif #ifndef S4WIN32 errno = 0 ; #endif for( ;; ) { #ifdef S4LOCKING #ifdef S4WINDOWS _llseek( file->hand, posStart, 0 ) ; #else lseek( file->hand, posStart, 0 ) ; #endif #ifdef S4MULTIC4 if ((pid = fork())<0) return error4(c4, e4lock, E80609); if (pid ==0) { #ifdef S4LOCKF if ( numAttempts == WAIT4EVER ) /* sleep until lock */ rc = lockf( file->hand, F_LOCK, numBytes ) ; else rc = lockf( file->hand, F_TLOCK, numBytes ) ; #else rc = locking( file->hand, LK_NBLCK, numBytes ) ; #endif exit(rc); } while (wait(&status)!=pid) ; if ((WIFEXITED(status)==0)) return error4(c4, e4lock, E80609); if ((rc=WEXITSTATUS(status)) == 0) { #ifdef S4LOCKF if ( numAttempts == WAIT4EVER ) /* sleep until lock */ rc = lockf( file->hand, F_LOCK, numBytes ) ; else rc = lockf( file->hand, F_TLOCK, numBytes ) ; #else rc = locking( file->hand, LK_NBLCK, numBytes ) ; #endif } #else #ifdef S4LOCKF if ( numAttempts == WAIT4EVER ) /* sleep until lock */ rc = lockf( file->hand, F_LOCK, numBytes ) ; else rc = lockf( file->hand, F_TLOCK, numBytes ) ; #else rc = locking( file->hand, LK_NBLCK, numBytes ) ; #endif #endif /* !S4MULTIC4 */ #else #ifdef S4IBMOS2 L4RANGE.FileOffset = posStart ; L4RANGE.RangeLength = numBytes ; rc = DosSetFileLocks( (HFILE) file->hand, 0L,(PFILELOCK) &L4RANGE, 100L, 0L ) ; #endif /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ #ifdef __TURBOC__ rc = lock( file->hand, posStart, numBytes ) ; #endif #ifdef S4WIN32 if ( LockFile( (HANDLE)file->hand, posStart, 0, numBytes, 0 ) ) rc = NO_ERROR ; else rc = GetLastError() ; #endif #endif #ifdef __ZTC__ if (rc == 0 || errno == 1) #else #ifdef S4IBMOS2 if (rc == NO_ERROR ) #else /* */ /* */ /* */ #ifdef S4WIN32 if (rc == NO_ERROR ) #else if (rc == 0 || errno == EINVAL) #endif /* */ #endif #endif { #ifdef S4LOCK_CHECK l4lock_save( file->hand, posStart, numBytes ) ; #endif return 0 ; } if ( rc == 0 ) { #ifdef S4LOCK_CHECK l4lock_save( file->hand, posStart, numBytes ) ; #endif #ifndef S4OPTIMIZE_OFF file4setWriteOpt( file, 1 ) ; #endif return 0 ; } #ifdef S4WIN32 if ( rc != ERROR_LOCK_VIOLATION ) #else #ifdef _MSC_VER #if _MSC_VER == 600 #ifdef S4WINDOWS if (errno != -1 ) /* Microsoft 6.00a does not return */ #else /* valid 'errno' under Windows, */ if (errno != EACCES) /* but performs locking correctly */ #endif #else if (errno != EACCES) #endif #else #ifdef __ZTC__ if (errno != 33) #else #ifdef S4IBMOS2 if ( rc != ERROR_LOCK_VIOLATION ) #else /* */ /* */ /* */ if (errno != EACCES && errno != 0 ) /* */ #endif #endif #endif #endif return error4describe( c4, e4lock,E90613, file->name, (char *)0, (char *)0 ) ; #ifdef S4LOCK_HOOK rc = code4lockHook( c4, file->name, 0, 0, -2, ++numAttempts ) ; if( rc != 0 ) return rc ; #else if ( numAttempts == 1 ) return r4locked ; if ( numAttempts > 1 ) numAttempts-- ; #endif #ifdef S4TEMP if ( d4display_quit( &display ) ) return error4( c4, e4result, E80604 ) ; #endif u4delayHundredth( (unsigned int)c4->lockDelay ) ; /* delay & try lock again */ } #endif } #ifdef S4LOCK_MODE_REQD /* tests for workaround to Novell same process lock inconsistency/bug */ /* returns '1' if overlapping locks are allowed by same process on file */ int file4lockMode( FILE4 *file ) { int rc, lockMode, oldLockAttempts ; CODE4 *c4 ; if ( file->hand == -1 ) return -1 ; c4 = file->codeBase ; lockMode = 0 ; oldLockAttempts = c4->lockAttempts ; c4->lockAttempts = 1 ; if ( file4lock( file, 0x50000000L, 2L ) != 0 ) { c4->lockAttempts = oldLockAttempts ; return -1 ; } rc = file4lock( file, 0x50000000L, 1L ) ; if ( rc == 0 ) { lockMode = 1 ; file4unlock( file, 0x50000000L, 1L ) ; } if ( rc < 0 ) lockMode = rc ; file4unlock( file, 0x50000000L, 2L ) ; c4->lockAttempts = oldLockAttempts ; return lockMode ; } #endif #ifdef P4ARGS_USED #pragma argsused #endif int S4FUNCTION file4unlock( FILE4 *file, long posStart, long numBytes ) { #ifndef S4SINGLE int rc ; #ifdef S4IBMOS2 struct LockStrc { long FileOffset ; long RangeLength ; } L4RANGE ; #endif /* */ /* */ /* */ #ifdef E4PARM_HIGH if ( file == 0 ) return error4( 0, e4parm_null, E90614 ) ; #ifndef S4MDX if ( numBytes < 0 || posStart < 0 ) return error4( file->codeBase, e4parm, E90614 ) ; #endif #endif if ( numBytes == 0 || file->isReadOnly || file->lowAccessMode != OPEN4DENY_NONE ) return 0 ; #ifndef S4OPTIMIZE_OFF file4setWriteOpt( file, 0 ) ; #endif #ifdef S4LOCK_CHECK l4lockRemove( file->hand, posStart, numBytes ) ; #endif #ifndef S4WIN32 errno = 0 ; #endif #ifdef S4LOCKING #ifdef S4WINDOWS _llseek( file->hand, posStart, 0 ) ; #else lseek( file->hand, posStart, 0 ) ; #endif #ifdef S4LOCKF /* lockf() replaces locking() for SUN OS, AT&T */ rc = lockf( file->hand, F_ULOCK, numBytes ) ; #else rc = locking( file->hand, LK_UNLCK, numBytes ) ; #endif #else #ifdef S4IBMOS2 L4RANGE.FileOffset = posStart ; L4RANGE.RangeLength = numBytes ; rc = DosSetFileLocks( (HFILE)file->hand, (PFILELOCK)&L4RANGE, 0L, 100L , 0L ) ; #endif /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ #ifdef __TURBOC__ rc = unlock( file->hand, posStart, numBytes ) ; #endif #ifdef S4WIN32 if ( UnlockFile( (HANDLE)file->hand, posStart, 0, numBytes, 0 ) ) rc = NO_ERROR ; else rc = -1 ; #endif #endif #ifdef __ZTC__ if ( rc < 0 && errno != 1 ) #else #ifdef S4IBMOS2 if ( rc != NO_ERROR ) #else /* */ /* */ /* */ #ifdef S4WIN32 if (rc != NO_ERROR ) #else if ( rc < 0 && errno != EINVAL ) #endif /* */ #endif #endif return error4describe( file->codeBase, e4unlock, E90614, file->name, (char *)0, (char *)0 ) ; #endif return 0 ; }