af15e0698b
git-svn-id: svn://10.65.10.50/trunk@4679 c028cbd2-c16b-5b4b-a496-9718f37d4682
609 lines
15 KiB
C
Executable File
609 lines
15 KiB
C
Executable File
/* f4lock.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
|
|
|
|
#include "d4all.h"
|
|
#ifdef S4IBMOS2
|
|
#define INCL_DOSFILEMGR
|
|
#include <os2.h>
|
|
#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 <unistd.h>
|
|
#else
|
|
/* */
|
|
#include <sys/locking.h>
|
|
/* */
|
|
#endif
|
|
#else
|
|
#ifndef S4WIN32
|
|
#ifndef __TURBOC__
|
|
#ifndef S4IBMOS2
|
|
#include <sys\locking.h>
|
|
#define S4LOCKING
|
|
#endif
|
|
#endif
|
|
#ifdef __ZTC__
|
|
extern int errno ;
|
|
#endif
|
|
#ifdef _MSC_VER
|
|
#include <sys\types.h>
|
|
#endif
|
|
#ifdef __TURBOC__
|
|
#ifndef S4OS2
|
|
#ifdef __BORLANDC__
|
|
#include <sys\locking.h> /* Borland C++ compilers */
|
|
#else
|
|
#include <locking.h> /* Turbo C++ for DOS compilers */
|
|
/* #include <sys\locking.h> */ /* Turbo C++ for Win compilers */
|
|
#endif
|
|
/* extern int cdecl errno ; */
|
|
#endif
|
|
#endif
|
|
/* #include <sys\stat.h>*/
|
|
/* #include <share.h>*/
|
|
#endif
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifndef S4WIN32
|
|
/* #include <fcntl.h>*/
|
|
#include <errno.h>
|
|
#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 ;
|
|
}
|