示例#1
0
文件: filebuf.c 项目: culikr/core
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;
}
示例#2
0
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;
}
示例#3
0
文件: filebuf.c 项目: culikr/core
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();
}
示例#4
0
文件: gtclip.c 项目: JamesLinus/core
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;
}
示例#5
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;
}
示例#6
0
文件: gtclip.c 项目: JamesLinus/core
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;
}
示例#7
0
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;
}
示例#8
0
文件: hbserv.c 项目: CsBela/core
/* -------------------------------
   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;
}
示例#9
0
文件: hbserv.c 项目: CsBela/core
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
}
示例#10
0
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
}
示例#11
0
文件: filebuf.c 项目: culikr/core
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;
}