static HB_BOOL s_fileLock( PHB_FILE pFile, HB_FOFFSET nStart, HB_FOFFSET nLen, int iType ) { HB_BOOL fResult, fLockFS = HB_FALSE; hb_vmUnlock(); if( ( iType & FL_MASK ) == FL_UNLOCK ) { hb_threadEnterCriticalSection( &s_lockMtx ); fResult = hb_fileUnlock( pFile, &fLockFS, nStart, nLen ); hb_threadLeaveCriticalSection( &s_lockMtx ); if( fLockFS ) { hb_fsLockLarge( pFile->hFile, nStart, nLen, ( HB_USHORT ) iType ); hb_threadEnterCriticalSection( &s_lockMtx ); hb_fileUnlock( pFile, NULL, nStart, nLen ); hb_threadLeaveCriticalSection( &s_lockMtx ); } else hb_fsSetError( fResult ? 0 : 33 ); } else { hb_threadEnterCriticalSection( &s_lockMtx ); fResult = hb_fileSetLock( pFile, &fLockFS, nStart, nLen ); hb_threadLeaveCriticalSection( &s_lockMtx ); if( fLockFS ) { #if defined( HB_OS_UNIX ) if( pFile->mode == FO_READ ) iType |= FLX_SHARED; else if( pFile->mode == FO_WRITE ) iType &= ~FLX_SHARED; #endif fResult = hb_fsLockLarge( pFile->hFile, nStart, nLen, ( HB_USHORT ) iType ); if( ! fResult ) { hb_threadEnterCriticalSection( &s_lockMtx ); hb_fileUnlock( pFile, NULL, nStart, nLen ); hb_threadLeaveCriticalSection( &s_lockMtx ); } } else hb_fsSetError( fResult ? 0 : 33 ); } hb_vmLock(); return fResult; }
static int s_fileLockTest( PHB_FILE pFile, HB_FOFFSET nStart, HB_FOFFSET nLen, int iType ) { HB_BOOL fLocked; int iResult; hb_vmUnlock(); 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 ); hb_vmLock(); return iResult; }
static void s_fileClose( PHB_FILE pFile ) { hb_vmUnlock(); hb_fsSetError( 0 ); hb_threadEnterCriticalSection( &s_fileMtx ); if( --pFile->used == 0 ) { if( pFile->pNext ) { pFile->pPrev->pNext = pFile->pNext; pFile->pNext->pPrev = pFile->pPrev; if( pFile == s_openFiles ) { s_openFiles = pFile->pNext; if( pFile == s_openFiles ) s_openFiles = NULL; } } if( pFile->hFile != FS_ERROR ) hb_fsClose( pFile->hFile ); if( pFile->hFileRO != FS_ERROR ) hb_fsClose( pFile->hFileRO ); if( pFile->pLocks ) hb_xfree( pFile->pLocks ); hb_xfree( pFile ); } hb_threadLeaveCriticalSection( &s_fileMtx ); hb_vmLock(); }
HB_BOOL hb_gt_getClipboard( char ** pszClipData, HB_SIZE * pnLen ) { hb_threadEnterCriticalSection( &s_clipMtx ); *pszClipData = NULL; *pnLen = s_nClipboardLen; if( s_nClipboardLen ) { *pszClipData = ( char * ) hb_xgrab( s_nClipboardLen + 1 ); memcpy( *pszClipData, s_szClipboardData, s_nClipboardLen ); ( *pszClipData )[ s_nClipboardLen ] = '\0'; } hb_threadLeaveCriticalSection( &s_clipMtx ); return s_nClipboardLen != 0; }
HB_BOOL hb_fileRegister( const HB_FILE_FUNCS * pFuncs ) { HB_BOOL fResult = HB_FALSE; hb_threadEnterCriticalSection( &s_fileMtx ); if( s_iFileTypes < HB_FILE_TYPE_MAX ) { s_pFileTypes[ s_iFileTypes ] = pFuncs; s_iFileTypes++; fResult = HB_TRUE; } hb_threadLeaveCriticalSection( &s_fileMtx ); return fResult; }
HB_BOOL hb_gt_setClipboard( const char * szClipData, HB_SIZE nLen ) { hb_threadEnterCriticalSection( &s_clipMtx ); if( s_nClipboardLen ) hb_xfree( s_szClipboardData ); s_nClipboardLen = nLen; if( nLen ) { s_szClipboardData = ( char * ) hb_xgrab( s_nClipboardLen + 1 ); memcpy( s_szClipboardData, szClipData, s_nClipboardLen ); s_szClipboardData[ s_nClipboardLen ] = '\0'; } hb_threadLeaveCriticalSection( &s_clipMtx ); return HB_TRUE; }
static PHB_FILE s_fileExtOpen( PHB_FILE_FUNCS pFuncs, const char * pszFileName, const char * pDefExt, HB_USHORT uiExFlags, const char * pPaths, PHB_ITEM pError ) { PHB_FILE pFile = NULL; #if defined( HB_OS_UNIX ) HB_BOOL fResult, fSeek = HB_FALSE; # if defined( HB_USE_LARGEFILE64 ) struct stat64 statbuf; # else struct stat statbuf; # endif #endif HB_BOOL fShared, fReadonly; HB_FHANDLE hFile; char * pszFile; HB_SYMBOL_UNUSED( pFuncs ); fShared = ( uiExFlags & ( FO_DENYREAD | FO_DENYWRITE | FO_EXCLUSIVE ) ) == 0; fReadonly = ( uiExFlags & ( FO_READ | FO_WRITE | FO_READWRITE ) ) == FO_READ; pszFile = hb_fsExtName( pszFileName, pDefExt, uiExFlags, pPaths ); hb_vmUnlock(); #if defined( HB_OS_UNIX ) # if defined( HB_USE_LARGEFILE64 ) fResult = stat64( ( char * ) pszFile, &statbuf ) == 0; # else fResult = stat( ( char * ) pszFile, &statbuf ) == 0; # endif hb_fsSetIOError( fResult, 0 ); if( fResult ) { hb_threadEnterCriticalSection( &s_fileMtx ); pFile = hb_fileFind( statbuf.st_dev, statbuf.st_ino ); if( pFile ) { if( ! fShared || ! pFile->shared || ( uiExFlags & FXO_TRUNCATE ) != 0 ) fResult = HB_FALSE; else if( ! fReadonly && pFile->readonly ) pFile = NULL; else pFile->used++; if( ( uiExFlags & FXO_NOSEEKPOS ) == 0 ) { # if defined( HB_OS_VXWORKS ) fSeek = ! S_ISFIFO( statbuf.st_mode ); # else fSeek = ! S_ISFIFO( statbuf.st_mode ) && ! S_ISSOCK( statbuf.st_mode ); # endif } } hb_threadLeaveCriticalSection( &s_fileMtx ); } if( pFile ) { if( ! fResult ) { hb_fsSetError( ( uiExFlags & FXO_TRUNCATE ) ? 5 : 32 ); pFile = NULL; } else if( uiExFlags & FXO_COPYNAME ) hb_strncpy( ( char * ) pszFileName, pszFile, HB_PATH_MAX - 1 ); if( pError ) { hb_errPutFileName( pError, pszFile ); if( ! fResult ) { hb_errPutOsCode( pError, hb_fsError() ); hb_errPutGenCode( pError, ( HB_ERRCODE ) ( ( uiExFlags & FXO_TRUNCATE ) ? EG_CREATE : EG_OPEN ) ); } } } else #endif { hFile = hb_fsExtOpen( pszFileName, pDefExt, uiExFlags, pPaths, pError ); if( hFile != FS_ERROR ) { HB_ULONG device = 0, inode = 0; #if defined( HB_OS_UNIX ) # if defined( HB_USE_LARGEFILE64 ) if( fstat64( hFile, &statbuf ) == 0 ) # else if( fstat( hFile, &statbuf ) == 0 ) # endif { device = ( HB_ULONG ) statbuf.st_dev; inode = ( HB_ULONG ) statbuf.st_ino; if( ( uiExFlags & FXO_NOSEEKPOS ) == 0 ) { # if defined( HB_OS_VXWORKS ) fSeek = ! S_ISFIFO( statbuf.st_mode ); # else fSeek = ! S_ISFIFO( statbuf.st_mode ) && ! S_ISSOCK( statbuf.st_mode ); # endif } } #endif hb_threadEnterCriticalSection( &s_fileMtx ); pFile = hb_fileNew( hFile, fShared, fReadonly, device, inode, HB_TRUE ); if( pFile->hFile != hFile ) { if( pFile->hFileRO == FS_ERROR && ! fReadonly && pFile->readonly ) { pFile->hFileRO = pFile->hFile; pFile->hFile = hFile; pFile->readonly = HB_FALSE; hFile = FS_ERROR; } if( pFile->uiLocks == 0 ) { #if ! defined( HB_USE_SHARELOCKS ) || defined( HB_USE_BSDLOCKS ) if( pFile->hFileRO != FS_ERROR ) { hb_fsClose( pFile->hFileRO ); pFile->hFileRO = FS_ERROR; } #endif if( hFile != FS_ERROR ) { hb_fsClose( hFile ); hFile = FS_ERROR; #if defined( HB_USE_SHARELOCKS ) && ! defined( HB_USE_BSDLOCKS ) /* TOFIX: possible race condition */ hb_fsLockLarge( hFile, HB_SHARELOCK_POS, HB_SHARELOCK_SIZE, FL_LOCK | FLX_SHARED ); #endif } } } else hFile = FS_ERROR; hb_threadLeaveCriticalSection( &s_fileMtx ); if( hFile != FS_ERROR ) { /* TOFIX: possible race condition in MT mode, * close() is not safe due to existing locks * which are removed. */ hb_fsClose( hFile ); } } } hb_xfree( pszFile ); #if defined( HB_OS_UNIX ) if( pFile && fSeek ) pFile = hb_fileposNew( pFile ); #endif hb_vmLock(); return pFile; }
/* ------------------------------- Manager of signals for windows */ static LONG s_signalHandler( int type, int sig, PEXCEPTION_RECORD exc ) { PHB_ITEM pFunction, pExecArray, pRet; HB_SIZE nPos; HB_UINT uiSig, uiMask; int iRet; /* let's find the right signal handler. */ hb_threadEnterCriticalSection( &s_ServiceMutex ); /* avoid working if PRG signal handling has been disabled */ if( ! bSignalEnabled ) { hb_threadLeaveCriticalSection( &s_ServiceMutex ); return EXCEPTION_EXECUTE_HANDLER; } bSignalEnabled = HB_FALSE; nPos = hb_arrayLen( sp_hooks ); /* subsig not necessary */ uiSig = ( HB_UINT ) s_translateSignal( ( HB_UINT ) type, ( HB_UINT ) sig ); while( nPos > 0 ) { pFunction = hb_arrayGetItemPtr( sp_hooks, nPos ); uiMask = ( HB_UINT ) hb_arrayGetNI( pFunction, 1 ); if( ( uiMask & uiSig ) == uiSig ) { /* we don't unlock the mutex now, even if it is a little dangerous. But we are in a signal hander... for now just 2 parameters */ pExecArray = hb_itemArrayNew( 3 ); hb_arraySetForward( pExecArray, 1, hb_arrayGetItemPtr( pFunction, 2 ) ); hb_arraySetNI( pExecArray, 2, uiSig ); /* the third parameter is an array: * 1: low-level signal * 2: low-level subsignal * 3: low-level system error * 4: address that rised the signal * 5: process id of the signal riser * 6: UID of the riser */ pRet = hb_arrayGetItemPtr( pExecArray, 3 ); hb_arrayNew( pRet, 6 ); hb_arraySetNI( pRet, HB_SERVICE_OSSIGNAL, type ); hb_arraySetNI( pRet, HB_SERVICE_OSSUBSIG, sig ); /* could be meaningless, but does not matter here */ hb_arraySetNI( pRet, HB_SERVICE_OSERROR, GetLastError() ); if( type == 0 ) /* exception */ { hb_arraySetPtr( pRet, HB_SERVICE_ADDRESS, ( void * ) exc->ExceptionAddress ); } else { hb_arraySetPtr( pRet, HB_SERVICE_ADDRESS, NULL ); } /* TODO: */ hb_arraySetNI( pRet, HB_SERVICE_PROCESS, GetCurrentThreadId() ); /* TODO: */ hb_arraySetNI( pRet, HB_SERVICE_UID, 0 ); pRet = hb_itemDo( pExecArray, 0 ); iRet = hb_itemGetNI( pRet ); hb_itemRelease( pRet ); hb_itemRelease( pExecArray ); switch( iRet ) { case HB_SERVICE_HANDLED: bSignalEnabled = HB_TRUE; hb_threadLeaveCriticalSection( &s_ServiceMutex ); return EXCEPTION_CONTINUE_EXECUTION; case HB_SERVICE_QUIT: bSignalEnabled = HB_FALSE; hb_threadLeaveCriticalSection( &s_ServiceMutex ); hb_vmRequestQuit(); #ifndef HB_THREAD_SUPPORT hb_vmQuit(); exit( 0 ); #else hb_threadCancelInternal(); #endif } } nPos--; } bSignalEnabled = HB_TRUE; return EXCEPTION_EXECUTE_HANDLER; }
static void s_signalHandler( int sig, siginfo_t * info, void * v ) #endif { HB_UINT uiMask; HB_UINT uiSig; PHB_ITEM pFunction, pExecArray, pRet; HB_SIZE nPos; int iRet; #if ! ( defined( HB_OS_OS2_GCC ) || defined( __WATCOMC__ ) ) HB_SYMBOL_UNUSED( v ); #endif /* let's find the right signal handler. */ hb_threadEnterCriticalSection( &s_ServiceMutex ); /* avoid working if PRG signal handling has been disabled */ if( ! bSignalEnabled ) { hb_threadLeaveCriticalSection( &s_ServiceMutex ); return; } bSignalEnabled = HB_FALSE; nPos = hb_arrayLen( sp_hooks ); /* subsig not necessary */ uiSig = ( HB_UINT ) s_translateSignal( ( HB_UINT ) sig, 0 ); while( nPos > 0 ) { pFunction = hb_arrayGetItemPtr( sp_hooks, nPos ); uiMask = ( HB_UINT ) hb_arrayGetNI( pFunction, 1 ); if( uiMask & uiSig ) { /* we don't unlock the mutex now, even if it is a little dangerous. But we are in a signal hander... for now just 2 parameters */ pExecArray = hb_itemArrayNew( 3 ); hb_arraySet( pExecArray, 1, hb_arrayGetItemPtr( pFunction, 2 ) ); hb_arraySetNI( pExecArray, 2, uiSig ); /* the third parameter is an array: */ pRet = hb_arrayGetItemPtr( pExecArray, 3 ); #if defined( HB_OS_OS2_GCC ) || defined( __WATCOMC__ ) hb_arrayNew( pRet, 1 ); #elif defined( HB_OS_BSD ) hb_arrayNew( pRet, info ? 6 : 1 ); #else hb_arrayNew( pRet, 6 ); #endif hb_arraySetNI( pRet, HB_SERVICE_OSSIGNAL, sig ); #if ! ( defined( HB_OS_OS2_GCC ) || defined( __WATCOMC__ ) ) #if defined( HB_OS_BSD ) if( info ) #endif { hb_arraySetNI( pRet, HB_SERVICE_OSSUBSIG, info->si_code ); #if ! defined( HB_OS_VXWORKS ) hb_arraySetNI( pRet, HB_SERVICE_OSERROR, info->si_errno ); hb_arraySetPtr( pRet, HB_SERVICE_ADDRESS, ( void * ) info->si_addr ); hb_arraySetNI( pRet, HB_SERVICE_PROCESS, info->si_pid ); hb_arraySetNI( pRet, HB_SERVICE_UID, info->si_uid ); #endif } #endif pRet = hb_itemDo( pExecArray, 0 ); iRet = hb_itemGetNI( pRet ); hb_itemRelease( pRet ); hb_itemRelease( pExecArray ); switch( iRet ) { case HB_SERVICE_HANDLED: bSignalEnabled = HB_TRUE; hb_threadLeaveCriticalSection( &s_ServiceMutex ); return; case HB_SERVICE_QUIT: bSignalEnabled = HB_FALSE; hb_threadLeaveCriticalSection( &s_ServiceMutex ); /* TODO: A service cleanup routine */ hb_vmRequestQuit(); /* Allow signals to go through pthreads */ s_serviceSetDflSig(); /* NOTICE: should be pthread_exit(0), but a bug in linuxthread prevents it: calling pthread exit from a signal handler will cause infinite wait for restart signal. This solution is rude, while the other would allow clean VM termination... but it works. */ exit( 0 ); } } nPos--; } bSignalEnabled = HB_TRUE; /*s_serviceSetHBSig();*/ #if 0 if( uiSig != HB_SIGNAL_UNKNOWN ) { if( sa_oldAction[ sig ].sa_flags & SA_SIGINFO ) sa_oldAction[ sig ].sa_sigaction( sig, info, v ); else sa_oldAction[ sig ].sa_handler( sig ); } #endif }
void * hb_stackGetTSD( PHB_TSD pTSD ) { HB_STACK_TLS_PRELOAD HB_TRACE( HB_TR_DEBUG, ( "hb_stackGetTSD(%p)", pTSD ) ); #if defined( HB_MT_VM ) if( pTSD->iHandle == 0 || pTSD->iHandle > hb_stack.iTSD || hb_stack.pTSD[ pTSD->iHandle ].pTSD == NULL ) { if( pTSD->iHandle == 0 ) { hb_threadEnterCriticalSection( &TSD_counter ); /* repeated test protected by mutex to avoid race condition */ if( pTSD->iHandle == 0 ) pTSD->iHandle = ++s_iTSDCounter; hb_threadLeaveCriticalSection( &TSD_counter ); } if( pTSD->iHandle > hb_stack.iTSD ) { hb_stack.pTSD = ( PHB_TSD_HOLDER ) hb_xrealloc( hb_stack.pTSD, ( pTSD->iHandle + 1 ) * sizeof( HB_TSD_HOLDER ) ); memset( &hb_stack.pTSD[ hb_stack.iTSD + 1 ], 0, ( pTSD->iHandle - hb_stack.iTSD ) * sizeof( HB_TSD_HOLDER ) ); hb_stack.iTSD = pTSD->iHandle; } #else if( pTSD->iHandle == 0 ) { HB_SIZE nSize = ( hb_stack.iTSD + 2 ) * sizeof( HB_TSD_HOLDER ); if( hb_stack.iTSD == 0 ) { hb_stack.pTSD = ( PHB_TSD_HOLDER ) hb_xgrab( nSize ); memset( hb_stack.pTSD, 0, nSize ); } else { hb_stack.pTSD = ( PHB_TSD_HOLDER ) hb_xrealloc( hb_stack.pTSD, nSize ); } pTSD->iHandle = ++hb_stack.iTSD; #endif hb_stack.pTSD[ pTSD->iHandle ].pTSD = pTSD; hb_stack.pTSD[ pTSD->iHandle ].value = hb_xgrab( pTSD->iSize ); memset( hb_stack.pTSD[ pTSD->iHandle ].value, 0, pTSD->iSize ); if( pTSD->pInitFunc ) pTSD->pInitFunc( hb_stack.pTSD[ pTSD->iHandle ].value ); } return hb_stack.pTSD[ pTSD->iHandle ].value; } void * hb_stackTestTSD( PHB_TSD pTSD ) { HB_STACK_TLS_PRELOAD HB_TRACE( HB_TR_DEBUG, ( "hb_stackTestTSD(%p)", pTSD ) ); #if defined( HB_MT_VM ) return ( pTSD->iHandle && pTSD->iHandle <= hb_stack.iTSD ) ? hb_stack.pTSD[ pTSD->iHandle ].value : NULL; #else return pTSD->iHandle ? hb_stack.pTSD[ pTSD->iHandle ].value : NULL; #endif }
static PHB_FILE s_fileExtOpen( PHB_FILE_FUNCS pFuncs, const char * pszFileName, const char * pDefExt, HB_FATTR nExFlags, const char * pPaths, PHB_ITEM pError ) { PHB_FILE pFile = NULL; #if defined( HB_OS_UNIX ) HB_BOOL fSeek = HB_FALSE; # if defined( HB_USE_LARGEFILE64 ) struct stat64 statbuf; # else struct stat statbuf; # endif #endif HB_BOOL fResult, fShared; int iMode; HB_FHANDLE hFile; char * pszFile; HB_SYMBOL_UNUSED( pFuncs ); fShared = ( nExFlags & ( FO_DENYREAD | FO_DENYWRITE | FO_EXCLUSIVE ) ) == 0; iMode = ( int ) ( nExFlags & ( FO_READ | FO_WRITE | FO_READWRITE ) ); pszFile = hb_fsExtName( pszFileName, pDefExt, nExFlags, pPaths ); hb_vmUnlock(); #if ! defined( HB_OS_UNIX ) fResult = HB_TRUE; #else # if defined( HB_USE_SHARELOCKS ) && ! defined( HB_USE_BSDLOCKS ) if( nExFlags & FXO_SHARELOCK ) { if( iMode == FO_WRITE && fShared ) { if( access( ( char * ) pszFile, R_OK ) == 0 || access( ( char * ) pszFile, F_OK ) != 0 ) { nExFlags = ( nExFlags ^ FO_WRITE ) | FO_READWRITE; iMode = FO_READWRITE; } else nExFlags ^= FXO_SHARELOCK; } else if( iMode == FO_READ && ! fShared ) { nExFlags &= ~ ( HB_FATTR ) ( FO_DENYREAD | FO_DENYWRITE | FO_EXCLUSIVE ); fShared = HB_TRUE; } } # endif hb_threadEnterCriticalSection( &s_fileMtx ); # if defined( HB_USE_LARGEFILE64 ) fResult = stat64( ( char * ) pszFile, &statbuf ) == 0; # else fResult = stat( ( char * ) pszFile, &statbuf ) == 0; # endif hb_fsSetIOError( fResult, 0 ); if( fResult ) { pFile = hb_fileFind( ( HB_ULONG ) statbuf.st_dev, ( HB_ULONG ) statbuf.st_ino ); if( pFile ) { if( ! fShared || ! pFile->shared || ( nExFlags & FXO_TRUNCATE ) != 0 ) { fResult = HB_FALSE; pFile = NULL; } else if( pFile->mode != FO_READWRITE && pFile->mode != iMode ) { iMode = FO_READWRITE; pFile = NULL; } else { pFile->used++; if( ( nExFlags & FXO_NOSEEKPOS ) == 0 ) { # if defined( HB_OS_VXWORKS ) fSeek = ! S_ISFIFO( statbuf.st_mode ); # else fSeek = ! S_ISFIFO( statbuf.st_mode ) && ! S_ISSOCK( statbuf.st_mode ); # endif } } } } else fResult = HB_TRUE; if( fResult && pFile == NULL ) #endif /* HB_OS_UNIX */ { hFile = hb_fsExtOpen( pszFile, NULL, nExFlags & ~ ( HB_FATTR ) ( FXO_DEFAULTS | FXO_COPYNAME ), NULL, NULL ); if( hFile != FS_ERROR ) { HB_ULONG device = 0, inode = 0; #if ! defined( HB_OS_UNIX ) hb_threadEnterCriticalSection( &s_fileMtx ); #else # if defined( HB_USE_LARGEFILE64 ) if( fstat64( hFile, &statbuf ) == 0 ) # else if( fstat( hFile, &statbuf ) == 0 ) # endif { device = ( HB_ULONG ) statbuf.st_dev; inode = ( HB_ULONG ) statbuf.st_ino; if( ( nExFlags & FXO_NOSEEKPOS ) == 0 ) { # if defined( HB_OS_VXWORKS ) fSeek = ! S_ISFIFO( statbuf.st_mode ); # else fSeek = ! S_ISFIFO( statbuf.st_mode ) && ! S_ISSOCK( statbuf.st_mode ); # endif } } #endif /* HB_OS_UNIX */ pFile = hb_fileNew( hFile, fShared, iMode, device, inode, HB_TRUE ); if( pFile->hFile != hFile ) { if( pFile->mode != FO_READWRITE && iMode == FO_READWRITE ) { HB_FHANDLE hTemp = pFile->hFileRO; pFile->hFileRO = pFile->hFile; pFile->hFile = hFile; pFile->mode = iMode; hFile = hTemp; } if( ! fShared || ! pFile->shared || pFile->mode != FO_READWRITE ) { fResult = HB_FALSE; if( pFile->hFileRO == FS_ERROR && pFile->uiLocks != 0 ) { pFile->hFileRO = hFile; hFile = FS_ERROR; } } if( pFile->uiLocks == 0 ) { #if ! defined( HB_USE_SHARELOCKS ) || defined( HB_USE_BSDLOCKS ) if( pFile->hFileRO != FS_ERROR ) { hb_fsClose( pFile->hFileRO ); pFile->hFileRO = FS_ERROR; } #endif if( hFile != FS_ERROR ) { hb_fsClose( hFile ); hFile = FS_ERROR; #if defined( HB_USE_SHARELOCKS ) && ! defined( HB_USE_BSDLOCKS ) /* TOFIX: possible race condition */ hb_fsLockLarge( pFile->hFile, HB_SHARELOCK_POS, HB_SHARELOCK_SIZE, FL_LOCK | FLX_SHARED ); #endif } } if( !fResult ) { if( pFile ) { --pFile->used; pFile = NULL; } if( hFile != FS_ERROR ) { /* TOFIX: possible race condition in MT mode, * close() is not safe due to existing locks * which are removed. */ hb_fsClose( hFile ); } } } #if ! defined( HB_OS_UNIX ) hb_threadLeaveCriticalSection( &s_fileMtx ); #endif } } #if defined( HB_OS_UNIX ) hb_threadLeaveCriticalSection( &s_fileMtx ); if( pFile && fSeek ) pFile = hb_fileposNew( pFile ); #endif if( ! fResult ) hb_fsSetError( ( nExFlags & FXO_TRUNCATE ) ? 5 : 32 ); if( ( nExFlags & FXO_COPYNAME ) != 0 && pFile ) hb_strncpy( ( char * ) HB_UNCONST( pszFileName ), pszFile, HB_PATH_MAX - 1 ); if( pError ) { hb_errPutFileName( pError, pszFile ); if( ! fResult ) { hb_errPutOsCode( pError, hb_fsError() ); hb_errPutGenCode( pError, ( HB_ERRCODE ) ( ( nExFlags & FXO_TRUNCATE ) ? EG_CREATE : EG_OPEN ) ); } } hb_xfree( pszFile ); hb_vmLock(); return pFile; }