diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 74320304ed..37a05ce1b2 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,50 @@ The license applies to all entries newer than 2009-04-28. */ +2011-06-09 15:31 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbapifs.h + * harbour/src/rtl/filesys.c + % removed unnecessary PID setting in POSIX file lock function. + + added new C function: + int hb_fsLockTest( HB_FHANDLE hFileHandle, HB_FOFFSET nStart, + HB_FOFFSET nLength, HB_USHORT uiMode ); + It allows to test file range lock status. + It returns -1 on error, 0 when lock can be set and value greater + then 0 if part of given range is locked by other process. In POSIX + systems this value is PID of current lock owner. In other systems + it's always 1. + In uiMode only FLX_SHARED bit is significant. + + * harbour/include/hbapifs.h + * harbour/src/rtl/filebuf.c + + added new C function: + int hb_fileLockTest( PHB_FILE pFile, HB_FOFFSET nStart, + HB_FOFFSET nLen, int iType ); + It's redirected to hb_fsLockTest() + + * harbour/contrib/hbnetio/netio.h + * harbour/contrib/hbnetio/netiocli.c + * harbour/contrib/hbnetio/netiosrv.c + * harbour/contrib/hbmemio/memio.c + + implemented hb_fileLockTest() low level code + + * harbour/include/dbinfo.ch + + added DBI_LOCKTEST + + * harbour/src/rdd/dbf1.c + % small code simplification + + implemented DBI_LOCKTEST + dbInfo( DBI_LOCKTEST [, ] ) -> + returns corresponding results to C level hb_fsLockTest() function. + If current workarea is already locked then 0 is returned. + If low level FS is located on POSIX system (accessed directly or by + HBNETIO) then value greater then 0 is PID of current lock owner. + If the lock is hold by aliased area or other thread of calling + process then is current PID. In Other systems 1 is returned + when lock cannot be set in current workarea. + If is given then the test is for RLOCK() otherwise FLOCK() + operation. + 2011-06-07 18:15 UTC-0800 Pritpal Bedi (bedipritpal@hotmail.com) * contrib/hbide/ideactions.prg * contrib/hbide/idemain.prg diff --git a/harbour/contrib/hbmemio/memio.c b/harbour/contrib/hbmemio/memio.c index 1d628c9b42..808e69fed7 100644 --- a/harbour/contrib/hbmemio/memio.c +++ b/harbour/contrib/hbmemio/memio.c @@ -670,6 +670,15 @@ HB_MEMFS_EXPORT HB_BOOL hb_memfsLock( HB_FHANDLE hFile, HB_FOFFSET ulStart, HB_F return HB_TRUE; } +HB_MEMFS_EXPORT int hb_memfsLockTest( HB_FHANDLE hFile, HB_FOFFSET ulStart, HB_FOFFSET nLength, int iMode ) +{ + HB_SYMBOL_UNUSED( hFile ); + HB_SYMBOL_UNUSED( ulStart ); + HB_SYMBOL_UNUSED( nLength ); + HB_SYMBOL_UNUSED( iMode ); + return 0; +} + /****************************************************** * * I/O Driver for Memory file system @@ -790,6 +799,13 @@ static HB_BOOL s_fileLock( PHB_FILE pFile, HB_FOFFSET ulStart, } +static int s_fileLockTest( PHB_FILE pFile, HB_FOFFSET ulStart, + HB_FOFFSET nLen, int iType ) +{ + return hb_memfsLockTest( pFile->hFile, ulStart, nLen, iType ); +} + + static HB_SIZE s_fileReadAt( PHB_FILE pFile, void * buffer, HB_SIZE nSize, HB_FOFFSET llOffset ) { @@ -843,6 +859,7 @@ static const HB_FILE_FUNCS s_fileFuncs = s_fileOpen, s_fileClose, s_fileLock, + s_fileLockTest, s_fileReadAt, s_fileWriteAt, s_fileTruncAt, diff --git a/harbour/contrib/hbnetio/netio.h b/harbour/contrib/hbnetio/netio.h index 5ef39dfc88..aa464c920f 100644 --- a/harbour/contrib/hbnetio/netio.h +++ b/harbour/contrib/hbnetio/netio.h @@ -107,6 +107,7 @@ #define NETIO_SRVITEM 21 #define NETIO_SRVDATA 22 #define NETIO_SRVCLOSE 23 +#define NETIO_TESTLOCK 24 #define NETIO_CONNECTED 0x4321DEAD /* messages format */ @@ -118,6 +119,7 @@ /* { NETIO_READ, file_no[2], size[ 4 ], offset[ 8 ], ... } -> { NETIO_READ, read[ 4 ], err[ 4 ], ... } + data[ read ] */ /* { NETIO_WRITE, file_no[2], size[ 4 ], offset[ 8 ], ... } + data[ size ] -> { NETIO_WRITE, written[ 4 ], err[ 4 ], ... } */ /* { NETIO_LOCK, file_no[2], start[ 8 ], len[ 8 ], flags[ 2 ], ... } -> { NETIO_LOCK, ... } */ +/* { NETIO_TESTLOCK, file_no[2], start[ 8 ], len[ 8 ], flags[ 2 ], ... } -> { NETIO_TESTLOCK, result[ 4 ], ... } */ /* { NETIO_TRUNC, file_no[2], offset[ 8 ], ... } -> { NETIO_TRUNC, ... } */ /* { NETIO_SIZE, file_no[2], ... } -> { NETIO_SIZE, size[ 8 ], err[ 4 ], ... } */ /* { NETIO_COMMIT, file_no[2], ... } -> { NETIO_SYNC, ... } | NULL */ diff --git a/harbour/contrib/hbnetio/netiocli.c b/harbour/contrib/hbnetio/netiocli.c index 4630cb0ba2..9472184960 100644 --- a/harbour/contrib/hbnetio/netiocli.c +++ b/harbour/contrib/hbnetio/netiocli.c @@ -1611,6 +1611,33 @@ static HB_BOOL s_fileLock( PHB_FILE pFile, HB_FOFFSET ulStart, HB_FOFFSET ulLen, return fResult; } +static int s_fileLockTest( PHB_FILE pFile, HB_FOFFSET ulStart, HB_FOFFSET ulLen, + int iType ) +{ + int iResult = -1; + + if( s_fileConLock( pFile->conn ) ) + { + HB_BYTE msgbuf[ NETIO_MSGLEN ]; + + HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_TESTLOCK ); + HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd ); + HB_PUT_LE_UINT64( &msgbuf[ 6 ], ulStart ); + HB_PUT_LE_UINT64( &msgbuf[ 14 ], ulLen ); + HB_PUT_LE_UINT16( &msgbuf[ 22 ], ( HB_USHORT ) iType ); +#if NETIO_MSGLEN > 24 + memset( msgbuf + 24, '\0', sizeof( msgbuf ) - 24 ); +#endif + + if( s_fileSendMsg( pFile->conn, msgbuf, NULL, 0, HB_TRUE, HB_FALSE ) ) + iResult = HB_GET_LE_INT32( &msgbuf[ 4 ] ); + + s_fileConUnlock( pFile->conn ); + } + + return iResult; +} + static HB_SIZE s_fileReadAt( PHB_FILE pFile, void * data, HB_SIZE ulSize, HB_FOFFSET llOffset ) { @@ -1759,6 +1786,7 @@ static const HB_FILE_FUNCS * s_fileMethods( void ) s_fileOpen, s_fileClose, s_fileLock, + s_fileLockTest, s_fileReadAt, s_fileWriteAt, s_fileTruncAt, diff --git a/harbour/contrib/hbnetio/netiosrv.c b/harbour/contrib/hbnetio/netiosrv.c index 23c447d9c4..2583d044f5 100644 --- a/harbour/contrib/hbnetio/netiosrv.c +++ b/harbour/contrib/hbnetio/netiosrv.c @@ -751,7 +751,7 @@ HB_FUNC( NETIO_SERVER ) HB_BOOL fNoAnswer = HB_FALSE; HB_ERRCODE errCode = 0, errFsCode; long len = 0, size, size2; - int iFileNo, iStreamID; + int iFileNo, iStreamID, iResult; HB_U32 uiMsg; HB_USHORT uiFalgs; char * szExt; @@ -973,6 +973,7 @@ HB_FUNC( NETIO_SERVER ) case NETIO_UNLOCK: fNoAnswer = HB_TRUE; case NETIO_LOCK: + case NETIO_TESTLOCK: iFileNo = HB_GET_LE_UINT16( &msgbuf[ 4 ] ); llOffset = HB_GET_LE_INT64( &msgbuf[ 6 ] ); llSize = HB_GET_LE_INT64( &msgbuf[ 14 ] ); @@ -980,6 +981,15 @@ HB_FUNC( NETIO_SERVER ) pFile = s_srvFileGet( conn, iFileNo ); if( pFile == NULL ) errCode = NETIO_ERR_WRONG_FILE_HANDLE; + else if( uiMsg == NETIO_TESTLOCK ) + { + iResult = hb_fileLockTest( pFile, llOffset, llSize, uiFalgs ); + errFsCode = hb_fsError(); + HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg ); + HB_PUT_LE_UINT32( &msg[ 4 ], iResult ); + HB_PUT_LE_UINT32( &msg[ 8 ], errFsCode ); + memset( msg + 12, '\0', NETIO_MSGLEN - 4 ); + } else if( !hb_fileLock( pFile, llOffset, llSize, uiFalgs ) ) errCode = s_srvFsError(); else if( !fNoAnswer ) diff --git a/harbour/include/dbinfo.ch b/harbour/include/dbinfo.ch index e2fa78129e..0e117136a0 100644 --- a/harbour/include/dbinfo.ch +++ b/harbour/include/dbinfo.ch @@ -291,6 +291,7 @@ #define DBI_DIRTYREAD 143 /* Get/Set index dirty read flag */ #define DBI_POSITIONED 144 /* Is cursor positioned to valid record */ #define DBI_ISTEMPORARY 145 /* Is the table a temporary one? */ +#define DBI_LOCKTEST 146 /* record / file lock test */ /* RECORD MAP (RM) support */ #define DBI_RM_SUPPORTED 150 /* has WA RDD record map support? */ diff --git a/harbour/include/hbapifs.h b/harbour/include/hbapifs.h index eb469feacb..7b1fc34b0a 100644 --- a/harbour/include/hbapifs.h +++ b/harbour/include/hbapifs.h @@ -152,6 +152,8 @@ extern HB_EXPORT HB_BOOL hb_fsIsDevice ( HB_FHANDLE hFileHandle ); /* dete extern HB_EXPORT HB_BOOL hb_fsLock ( HB_FHANDLE hFileHandle, HB_ULONG ulStart, HB_ULONG ulLength, HB_USHORT uiMode ); /* request a lock on a portion of a file */ extern HB_EXPORT HB_BOOL hb_fsLockLarge ( HB_FHANDLE hFileHandle, HB_FOFFSET nStart, HB_FOFFSET nLength, HB_USHORT uiMode ); /* request a lock on a portion of a file using 64bit API */ +extern HB_EXPORT int hb_fsLockTest ( HB_FHANDLE hFileHandle, HB_FOFFSET nStart, + HB_FOFFSET nLength, HB_USHORT uiMode ); extern HB_EXPORT HB_BOOL hb_fsMkDir ( const char * pszDirName ); /* create a directory */ extern HB_EXPORT HB_FHANDLE hb_fsOpen ( const char * pszFileName, HB_USHORT uiFlags ); /* open a file */ extern HB_EXPORT HB_USHORT hb_fsRead ( HB_FHANDLE hFileHandle, void * pBuff, HB_USHORT uiCount ); /* read contents of a file into a buffer (<=64K) */ @@ -310,6 +312,7 @@ extern HB_EXPORT const char * hb_fsNameConv( const char * szFileName, char ** ps PHB_ITEM pError ); void (* Close ) ( PHB_FILE pFile ); HB_BOOL (* Lock ) ( PHB_FILE, HB_FOFFSET nStart, HB_FOFFSET nLen, int iType ); + int (* LockTest ) ( PHB_FILE, HB_FOFFSET nStart, HB_FOFFSET nLen, int iType ); HB_SIZE (* ReadAt ) ( PHB_FILE pFile, void * buffer, HB_SIZE nSize, HB_FOFFSET nOffset ); HB_SIZE (* WriteAt ) ( PHB_FILE pFile, const void * buffer, HB_SIZE nSize, HB_FOFFSET nOffset ); HB_BOOL (* TruncAt ) ( PHB_FILE pFile, HB_FOFFSET nOffset ); @@ -340,6 +343,7 @@ extern HB_EXPORT PHB_FILE hb_fileCreateTempEx( char * pszName, HB_FATTR ulAttr ); extern HB_EXPORT void hb_fileClose( PHB_FILE pFile ); extern HB_EXPORT HB_BOOL hb_fileLock( PHB_FILE pFile, HB_FOFFSET nStart, HB_FOFFSET nLen, int iType ); +extern HB_EXPORT int hb_fileLockTest( PHB_FILE pFile, HB_FOFFSET nStart, HB_FOFFSET nLen, int iType ); extern HB_EXPORT HB_SIZE hb_fileReadAt( PHB_FILE pFile, void * buffer, HB_SIZE nSize, HB_FOFFSET nOffset ); extern HB_EXPORT HB_SIZE hb_fileWriteAt( PHB_FILE pFile, const void * buffer, HB_SIZE nSize, HB_FOFFSET nOffset ); extern HB_EXPORT HB_BOOL hb_fileTruncAt( PHB_FILE pFile, HB_FOFFSET nOffset ); diff --git a/harbour/src/rdd/dbf1.c b/harbour/src/rdd/dbf1.c index 4ed2be04c0..98dbe33a09 100644 --- a/harbour/src/rdd/dbf1.c +++ b/harbour/src/rdd/dbf1.c @@ -1315,6 +1315,49 @@ static HB_ERRCODE hb_dbfLockData( DBFAREAP pArea, return HB_SUCCESS; } +static int hb_dbfLockTest( DBFAREAP pArea, HB_USHORT uiAction, HB_ULONG ulRecNo ) +{ + int iResult = -1; + + HB_TRACE(HB_TR_DEBUG, ("hb_dbfLockTest(%p, %hu, %lu)", pArea, uiAction, ulRecNo)); + + if( !pArea->fShared || pArea->fFLocked || + ( uiAction == REC_LOCK && hb_dbfIsLocked( pArea, ulRecNo ) ) ) + iResult = 0; + else + { + HB_FOFFSET nPos, nFlSize, nRlSize; + int iDir; + + if( hb_dbfLockData( pArea, &nPos, &nFlSize, &nRlSize, &iDir ) == HB_SUCCESS ) + { + switch( uiAction ) + { + case FILE_LOCK: + if( iDir < 0 ) + nPos -= nFlSize; + else + nPos++; + iResult = hb_fileLockTest( pArea->pDataFile, nPos, nFlSize, FL_LOCK ); + break; + + case REC_LOCK: + if( iDir < 0 ) + nPos -= ulRecNo; + else if( iDir == 2 ) + nPos += ( ulRecNo - 1 ) * pArea->uiRecordLen + pArea->uiHeaderLen; + else + nPos += ulRecNo; + + iResult = hb_fileLockTest( pArea->pDataFile, nPos, nRlSize, FL_LOCK ); + break; + } + } + } + + return iResult; +} + /* * -- DBF METHODS -- */ @@ -3408,6 +3451,13 @@ static HB_ERRCODE hb_dbfInfo( DBFAREAP pArea, HB_USHORT uiIndex, PHB_ITEM pItem break; } + case DBI_LOCKTEST: + if( HB_IS_NUMERIC( pItem ) ) + hb_itemPutNI( pItem, hb_dbfLockTest( pArea, REC_LOCK, hb_itemGetNL( pItem ) ) ); + else + hb_itemPutNI( pItem, hb_dbfLockTest( pArea, FILE_LOCK, 0 ) ); + break; + case DBI_LOCKSCHEME: { int iScheme = hb_itemGetNI( pItem ); @@ -4814,10 +4864,11 @@ static HB_ERRCODE hb_dbfRawLock( DBFAREAP pArea, HB_USHORT uiAction, HB_ULONG ul if( !pArea->fFLocked ) { if( iDir < 0 ) - fLck = hb_fileLock( pArea->pDataFile, nPos - nFlSize, nFlSize, FL_LOCK ); + nPos -= nFlSize; else - fLck = hb_fileLock( pArea->pDataFile, nPos + 1, nFlSize, FL_LOCK ); + nPos++; + fLck = hb_fileLock( pArea->pDataFile, nPos, nFlSize, FL_LOCK ); if( !fLck ) errCode = HB_FAILURE; else @@ -4829,10 +4880,11 @@ static HB_ERRCODE hb_dbfRawLock( DBFAREAP pArea, HB_USHORT uiAction, HB_ULONG ul if( pArea->fFLocked ) { if( iDir < 0 ) - fLck = hb_fileLock( pArea->pDataFile, nPos - nFlSize, nFlSize, FL_UNLOCK ); + nPos -= nFlSize; else - fLck = hb_fileLock( pArea->pDataFile, nPos + 1, nFlSize, FL_UNLOCK ); + nPos++; + fLck = hb_fileLock( pArea->pDataFile, nPos, nFlSize, FL_UNLOCK ); if( !fLck ) errCode = HB_FAILURE; pArea->fFLocked = HB_FALSE; @@ -4843,12 +4895,13 @@ static HB_ERRCODE hb_dbfRawLock( DBFAREAP pArea, HB_USHORT uiAction, HB_ULONG ul if( !pArea->fFLocked ) { if( iDir < 0 ) - fLck = hb_fileLock( pArea->pDataFile, nPos - ulRecNo, nRlSize, FL_LOCK ); + nPos -= ulRecNo; else if( iDir == 2 ) - fLck = hb_fileLock( pArea->pDataFile, nPos + ( ulRecNo - 1 ) * pArea->uiRecordLen + pArea->uiHeaderLen, nRlSize, FL_LOCK ); + nPos += ( ulRecNo - 1 ) * pArea->uiRecordLen + pArea->uiHeaderLen; else - fLck = hb_fileLock( pArea->pDataFile, nPos + ulRecNo, nRlSize, FL_LOCK ); + nPos += ulRecNo; + fLck = hb_fileLock( pArea->pDataFile, nPos, nRlSize, FL_LOCK ); if( !fLck ) errCode = HB_FAILURE; } @@ -4858,11 +4911,13 @@ static HB_ERRCODE hb_dbfRawLock( DBFAREAP pArea, HB_USHORT uiAction, HB_ULONG ul if( !pArea->fFLocked ) { if( iDir < 0 ) - fLck = hb_fileLock( pArea->pDataFile, nPos - ulRecNo, nRlSize, FL_UNLOCK ); + nPos -= ulRecNo; else if( iDir == 2 ) - fLck = hb_fileLock( pArea->pDataFile, nPos + ( ulRecNo - 1 ) * pArea->uiRecordLen + pArea->uiHeaderLen, nRlSize, FL_UNLOCK ); + nPos += ( ulRecNo - 1 ) * pArea->uiRecordLen + pArea->uiHeaderLen; else - fLck = hb_fileLock( pArea->pDataFile, nPos + ulRecNo, nRlSize, FL_UNLOCK ); + nPos += ulRecNo; + + fLck = hb_fileLock( pArea->pDataFile, nPos, nRlSize, FL_UNLOCK ); if( !fLck ) errCode = HB_FAILURE; } @@ -4875,7 +4930,7 @@ static HB_ERRCODE hb_dbfRawLock( DBFAREAP pArea, HB_USHORT uiAction, HB_ULONG ul for( ;; ) { fLck = hb_fileLock( pArea->pDataFile, nPos, 1, FL_LOCK | FLX_WAIT ); - /* TODO: call special error handler (LOCKHANDLER) hiere if !fLck */ + /* TODO: call special error handler (LOCKHANDLER) if !fLck */ if( fLck ) break; hb_releaseCPU(); diff --git a/harbour/src/rtl/filebuf.c b/harbour/src/rtl/filebuf.c index c9b548d0ba..d2feaa5483 100644 --- a/harbour/src/rtl/filebuf.c +++ b/harbour/src/rtl/filebuf.c @@ -63,6 +63,9 @@ #if !defined( HB_OS_WIN_CE ) # include # include +# if defined( HB_OS_UNIX ) +# include +# endif #endif @@ -303,6 +306,22 @@ static HB_BOOL hb_fileUnlock( PHB_FILE pFile, HB_BOOL * pfLockFS, return fResult; } +static HB_BOOL hb_fileTestLock( PHB_FILE pFile, + HB_FOFFSET nStart, HB_FOFFSET nLen ) +{ + HB_UINT uiPos; + + uiPos = hb_fileFindOffset( pFile, nStart ); + if( uiPos < pFile->uiLocks ) + { + PHB_FLOCK pLock = &pFile->pLocks[ uiPos ]; + if( nStart + nLen > pLock->start ) + return HB_TRUE; + } + + return HB_FALSE; +} + /* * file methods @@ -516,6 +535,29 @@ static HB_BOOL s_fileLock( PHB_FILE pFile, HB_FOFFSET nStart, HB_FOFFSET nLen, return fResult; } +static int s_fileLockTest( PHB_FILE pFile, HB_FOFFSET nStart, HB_FOFFSET nLen, + int iType ) +{ + HB_BOOL fLocked; + int iResult; + + hb_threadEnterCriticalSection( &s_fileMtx ); + fLocked = hb_fileTestLock( pFile, nStart, nLen ); + hb_threadLeaveCriticalSection( &s_fileMtx ); + if( fLocked ) + { +#if defined( HB_OS_UNIX ) + iResult = getpid(); +#else + iResult = 1; +#endif + } + else + iResult = hb_fsLockTest( pFile->hFile, nStart, nLen, ( HB_USHORT ) iType ); + + return iResult; +} + static HB_SIZE s_fileReadAt( PHB_FILE pFile, void * buffer, HB_SIZE nSize, HB_FOFFSET nOffset ) { @@ -566,6 +608,7 @@ static const HB_FILE_FUNCS * s_fileMethods( void ) s_fileExtOpen, s_fileClose, s_fileLock, + s_fileLockTest, s_fileReadAt, s_fileWriteAt, s_fileTruncAt, @@ -669,6 +712,12 @@ HB_BOOL hb_fileLock( PHB_FILE pFile, HB_FOFFSET nStart, HB_FOFFSET nLen, return pFile->pFuncs->Lock( pFile, nStart, nLen, iType ); } +int hb_fileLockTest( PHB_FILE pFile, HB_FOFFSET nStart, HB_FOFFSET nLen, + int iType ) +{ + return pFile->pFuncs->LockTest( pFile, nStart, nLen, iType ); +} + HB_SIZE hb_fileReadAt( PHB_FILE pFile, void * buffer, HB_SIZE nSize, HB_FOFFSET nOffset ) { diff --git a/harbour/src/rtl/filesys.c b/harbour/src/rtl/filesys.c index dcb12b9f01..b207312c51 100644 --- a/harbour/src/rtl/filesys.c +++ b/harbour/src/rtl/filesys.c @@ -2535,7 +2535,7 @@ HB_BOOL hb_fsLock( HB_FHANDLE hFileHandle, HB_ULONG ulStart, lock_info.l_start = ulStart; lock_info.l_len = ulLength; lock_info.l_whence = SEEK_SET; /* start from the beginning of the file */ - lock_info.l_pid = getpid(); + lock_info.l_pid = 0; HB_FAILURE_RETRY( iResult, fcntl( hFileHandle, ( uiMode & FLX_WAIT ) ? F_SETLKW: F_SETLK, @@ -2549,7 +2549,7 @@ HB_BOOL hb_fsLock( HB_FHANDLE hFileHandle, HB_ULONG ulStart, lock_info.l_start = ulStart; lock_info.l_len = ulLength; lock_info.l_whence = SEEK_SET; - lock_info.l_pid = getpid(); + lock_info.l_pid = 0; HB_FAILURE_RETRY( iResult, fcntl( hFileHandle, F_SETLK, &lock_info ) ); fResult = iResult != -1; @@ -2668,7 +2668,7 @@ HB_BOOL hb_fsLockLarge( HB_FHANDLE hFileHandle, HB_FOFFSET nStart, lock_info.l_start = nStart; lock_info.l_len = nLength; lock_info.l_whence = SEEK_SET; /* start from the beginning of the file */ - lock_info.l_pid = getpid(); + lock_info.l_pid = 0; HB_FAILURE_RETRY( iResult, fcntl( hFileHandle, ( uiMode & FLX_WAIT ) ? F_SETLKW64: F_SETLK64, @@ -2682,7 +2682,7 @@ HB_BOOL hb_fsLockLarge( HB_FHANDLE hFileHandle, HB_FOFFSET nStart, lock_info.l_start = nStart; lock_info.l_len = nLength; lock_info.l_whence = SEEK_SET; - lock_info.l_pid = getpid(); + lock_info.l_pid = 0; HB_FAILURE_RETRY( iResult, fcntl( hFileHandle, F_SETLK64, &lock_info ) ); fResult = iResult != -1; @@ -2701,6 +2701,52 @@ HB_BOOL hb_fsLockLarge( HB_FHANDLE hFileHandle, HB_FOFFSET nStart, return fResult; } +int hb_fsLockTest( HB_FHANDLE hFileHandle, HB_FOFFSET nStart, + HB_FOFFSET nLength, HB_USHORT uiMode ) +{ + int iResult; + + HB_TRACE(HB_TR_DEBUG, ("hb_fsLockTest(%p, %" PFHL "u, %" PFHL "i, %hu)", ( void * ) ( HB_PTRDIFF ) hFileHandle, nStart, nLength, uiMode)); + +#if defined( HB_OS_UNIX ) +{ +# if defined( HB_USE_LARGEFILE64 ) + struct flock64 lock_info; + + lock_info.l_type = ( uiMode & FLX_SHARED ) ? F_RDLCK : F_WRLCK;; + lock_info.l_start = nStart; + lock_info.l_len = nLength; + lock_info.l_whence = SEEK_SET; + lock_info.l_pid = 0; + iResult = fcntl( hFileHandle, F_GETLK64, &lock_info ) != -1 ? + ( int ) lock_info.l_pid : -1; +# else + struct flock lock_info; + + lock_info.l_type = ( uiMode & FLX_SHARED ) ? F_RDLCK : F_WRLCK;; + lock_info.l_start = nStart; + lock_info.l_len = nLength; + lock_info.l_whence = SEEK_SET; + lock_info.l_pid = 0; + iResult = fcntl( hFileHandle, F_GETLK, &lock_info ) != -1 ? + ( int ) lock_info.l_pid : -1; +# endif +} +#else + if( hb_fsLockLarge( hFileHandle, nStart, nLength, ( uiMode & FLX_SHARED ) | FL_LOCK ) ) + { + if( !hb_fsLockLarge( hFileHandle, nStart, nLength, FL_UNLOCK ) ) + iResult = -1; + else + iResult = 0; + } + else + iResult = 1; +#endif + + return iResult; +} + HB_ULONG hb_fsSeek( HB_FHANDLE hFileHandle, HB_LONG lOffset, HB_USHORT uiFlags ) { HB_ULONG ulPos;