/* * $Id$ */ /* * Harbour Project source code: * The FileSys API (C level) * * Copyright 1999 {list of individual authors and e-mail addresses} * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). * * As a special exception, the Harbour Project gives permission for * additional uses of the text contained in its release of Harbour. * * The exception is that, if you link the Harbour libraries with other * files to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public License. * Your use of that executable is in no way restricted on account of * linking the Harbour library code into it. * * This exception does not however invalidate any other reasons why * the executable file might be covered by the GNU General Public License. * * This exception applies only to the code released by the Harbour * Project under the name Harbour. If you copy code from other * Harbour Project or Free Software Foundation releases into a copy of * Harbour, as the General Public License permits, the exception does * not apply to the code that you add in this way. To avoid misleading * anyone as to the status of such modified files, you must delete * this exception notice from them. * * If you write modifications of your own for Harbour, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. * */ /* * The following parts are Copyright of the individual authors. * www - http://www.harbour-project.org * * Copyright 1999-2001 Viktor Szakats * hb_fsSetError() * hb_fsSetDevMode() * hb_fsReadLarge() * hb_fsWriteLarge() * hb_fsCurDirBuff() * * Copyright 1999 Jose Lalin * hb_fsChDrv() * hb_fsCurDrv() * hb_fsIsDrv() * hb_fsIsDevice() * * Copyright 2000 Luiz Rafael Culik * and David G. Holm * hb_fsEof() * * Copyright 2001 Jose Gimenez (JFG) * * Added __WIN32__ check for any compiler to use the Win32 * API calls to allow openning an unlimited number of files * simultaneously. * * See doc/license.txt for licensing terms. * */ /* NOTE: In DOS/DJGPP under WinNT4 hb_fsSeek( fhnd, offset < 0, FS_SET) will set the file pointer to the passed negative value, and the subsequent hb_fsWrite() call will fail. In CA-Clipper hb_fsSeek() will fail, the pointer will not be moved, and thus the hb_fsWrite() call will successfully write the buffer to the current file position. [vszakats] This has been corrected by ptucker */ #if defined(HB_OS_LINUX) # define _LARGEFILE64_SOURCE #endif #ifndef HB_OS_WIN_32_USED #define HB_OS_WIN_32_USED #endif #include #include #include "hbapi.h" #include "hbapifs.h" #include "hbset.h" #include "hb_io.h" #if defined(OS_UNIX_COMPATIBLE) #include #endif #if defined(__GNUC__) && !defined(__MINGW32__) #include #include #include #include #if defined(__CYGWIN__) #include #endif #if defined(__DJGPP__) #include #define _getdrive getdisk #define _chdrive setdisk #endif #if !defined(HAVE_POSIX_IO) #define HAVE_POSIX_IO #endif extern int rename( const char *, const char * ); #endif #if defined(__WATCOMC__) #include #include #include #include #include #include #if !defined(HAVE_POSIX_IO) #define HAVE_POSIX_IO #endif #define ftruncate chsize #endif #if defined(__BORLANDC__) || defined(__IBMCPP__) || defined(_MSC_VER) || defined(__MINGW32__) #include #include #include #include #if defined(__BORLANDC__) #include #include #include #endif #if defined(_MSC_VER) || defined(__MINGW32__) #include #define ftruncate _chsize #if defined(__MINGW32__) && !defined(_LK_UNLCK) #define _LK_UNLCK _LK_UNLOCK #endif #if defined(_MSC_VER) && !defined(HAVE_POSIX_IO) #define HAVE_POSIX_IO #endif #else #define ftruncate chsize #if !defined(HAVE_POSIX_IO) #define HAVE_POSIX_IO #endif #endif #include #endif #if defined(__MPW__) #include #endif #if defined(HB_OS_DOS) #include #endif #ifndef O_BINARY #define O_BINARY 0 /* O_BINARY not defined on Linux */ #endif #ifndef S_IEXEC #define S_IEXEC 0x0040 /* owner may execute */ #endif #ifndef S_IRWXU #define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) #endif #ifndef S_IRUSR #define S_IRUSR 0x0100 /* owner may read */ #endif #ifndef S_IWUSR #define S_IWUSR 0x0080 /* owner may write */ #endif #ifndef S_IXUSR #define S_IXUSR 0x0040 /* owner may execute */ #endif #ifndef S_IRWXG #define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) #endif #ifndef S_IRGRP #define S_IRGRP 0x00020 /* read permission, group */ #endif #ifndef S_IWGRP #define S_IWGRP 0x00010 /* write permission, grougroup */ #endif #ifndef S_IXGRP #define S_IXGRP 0x00008/* execute/search permission, group */ #endif #ifndef S_IRWXO #define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) #endif #ifndef S_IROTH #define S_IROTH 0x00004 /* read permission, other */ #endif #ifndef S_IWOTH #define S_IWOTH 0x00002 /* write permission, other */ #endif #ifndef S_IXOTH #define S_IXOTH 0x00001/* execute/search permission, other */ #endif #ifndef SH_COMPAT #define SH_COMPAT 0x00 /* Compatibility */ #endif #ifndef SH_DENYRW #define SH_DENYRW 0x10 /* Deny read/write */ #endif #ifndef SH_DENYWR #define SH_DENYWR 0x20 /* Deny write */ #endif #ifndef SH_DENYRD #define SH_DENYRD 0x30 /* Deny read */ #endif #ifndef SH_DENYNO #define SH_DENYNO 0x40 /* Deny nothing */ #endif static USHORT s_uiErrorLast = 0; #if defined(HAVE_POSIX_IO) || defined(_MSC_VER) || defined(__MINGW32__) /* Only compilers with Posix or Posix-like I/O support are supported */ #define HB_FS_FILE_IO #endif #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__IBMCPP__) || defined(__WATCOMC__) /* These compilers use sopen() rather than open(), because their versions of open() do not support combined O_ and SH_ flags */ #define HB_FS_SOPEN #endif #if ( defined(HAVE_POSIX_IO) && ( defined(HB_OS_OS2) || defined(HB_OS_DOS) || defined(HB_OS_WIN_32) ) && ! defined(__CYGWIN__) ) || defined(__MINGW32__) /* These platforms and/or compilers have common drive letter support */ #define HB_FS_DRIVE_LETTER #endif #if UINT_MAX == USHRT_MAX #define LARGE_MAX ( UINT_MAX - 1L ) #else #define HB_FS_LARGE_OPTIMIZED #endif #if defined(X__WIN32__) #if !defined(__BORLANDC__) extern int WintoDosError( DWORD dwError ); #else extern int __IOerror( int dosErr ); extern int __NTerror( void ); #endif static HANDLE DostoWinHandle( FHANDLE fHandle ); #endif /* Convert HARBOUR flags to IO subsystem flags */ #if defined(HB_FS_FILE_IO) extern char **environ; static int convert_open_flags( USHORT uiFlags ) { /* by default FO_READ + FO_COMPAT is set */ int result_flags = 0; HB_TRACE(HB_TR_DEBUG, ("convert_open_flags(%hu)", uiFlags)); result_flags |= O_BINARY; HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_BINARY\n")); #if defined(HB_FS_SOPEN) if( ( uiFlags & ( FO_WRITE | FO_READWRITE ) ) == FO_READ ) { result_flags |= O_RDONLY; HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_RDONLY\n")); } #else if( ( uiFlags & ( FO_WRITE | FO_READWRITE ) ) == FO_READ ) { result_flags |= ( O_RDONLY | SH_COMPAT ); HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_RDONLY SH_COMPAT\n")); } #endif /* read & write flags */ if( uiFlags & FO_WRITE ) { result_flags |= O_WRONLY; HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_WRONLY\n")); } if( uiFlags & FO_READWRITE ) { result_flags |= O_RDWR; HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_RDWR\n")); } #if ! defined(HB_FS_SOPEN) && ! defined( HB_OS_UNIX ) /* shared flags */ if( ( uiFlags & FO_DENYREAD ) == FO_DENYREAD ) { result_flags |= SH_DENYRD; HB_TRACE(HB_TR_INFO, ("convert_open_flags: added SH_DENYRD\n")); } else if( uiFlags & FO_EXCLUSIVE ) { result_flags |= SH_DENYRW; HB_TRACE(HB_TR_INFO, ("convert_open_flags: added SH_DENYRW\n")); } else if( uiFlags & FO_DENYWRITE ) { result_flags |= SH_DENYWR; HB_TRACE(HB_TR_INFO, ("convert_open_flags: added SH_DENYWR\n")); } if( uiFlags & FO_DENYNONE ) { result_flags |= SH_DENYNO; HB_TRACE(HB_TR_INFO, ("convert_open_flags: added SH_DENYNO\n")); } if( uiFlags & FO_SHARED ) { result_flags |= SH_DENYNO; HB_TRACE(HB_TR_INFO, ("convert_open_flags: added SH_DENYNO\n")); } #endif if( uiFlags & FO_CREAT ) { result_flags |= O_CREAT; HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_CREAT\n")); } if( uiFlags & FO_TRUNC ) { result_flags |= O_TRUNC; HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_TRUNC\n")); } if( uiFlags & FO_EXCL ) { result_flags |= O_EXCL; HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_EXCL\n")); } HB_TRACE(HB_TR_INFO, ("convert_open_flags: result is 0x%04x\n", result_flags)); return result_flags; } static unsigned convert_pmode_flags( USHORT uiFlags ) { unsigned result_pmode; HB_TRACE(HB_TR_DEBUG, ("convert_pmode_flags(%hu)", uiFlags)); if( uiFlags & FC_HIDDEN ) { result_pmode = S_IRUSR; } else { result_pmode = S_IRUSR | S_IRGRP | S_IROTH; } if( !( uiFlags & FC_READONLY) ) { if( result_pmode & S_IRUSR ) result_pmode |= S_IWUSR; if( result_pmode & S_IRGRP ) result_pmode |= S_IWGRP; if( result_pmode & S_IROTH ) result_pmode |= S_IWOTH; } if( uiFlags & FC_SYSTEM ) { if( result_pmode & S_IRUSR ) result_pmode |= S_IXUSR; if( result_pmode & S_IRGRP ) result_pmode |= S_IXGRP; if( result_pmode & S_IROTH ) result_pmode |= S_IXOTH; } HB_TRACE(HB_TR_INFO, ("convert_pmode_flags: 0x%04x\n", result_pmode)); return result_pmode; } static void convert_create_flags( USHORT uiFlags, int * result_flags, unsigned * result_pmode ) { HB_TRACE(HB_TR_DEBUG, ("convert_create_flags(%hu, %p, %p)", uiFlags, result_flags, result_pmode)); /* by default FC_NORMAL is set */ *result_flags = O_BINARY | O_CREAT | O_TRUNC | O_RDWR; *result_pmode = convert_pmode_flags( uiFlags ); HB_TRACE(HB_TR_INFO, ("convert_create_flags: 0x%04x, 0x%04x\n", *result_flags, *result_pmode)); } static void convert_create_flags_ex( USHORT uiAttr, USHORT uiFlags, int * result_flags, unsigned * result_pmode ) { HB_TRACE(HB_TR_DEBUG, ("convert_create_flags_ex(%hu, %hu, %p, %p)", uiAttr, uiFlags, result_flags, result_pmode)); /* by default FC_NORMAL is set */ /* *result_flags = O_BINARY | O_CREAT | O_TRUNC | O_RDWR; */ *result_flags = convert_open_flags( uiFlags ) | O_BINARY | O_CREAT | O_TRUNC | O_RDWR; if ( uiFlags & FO_EXCL ) *result_flags |= O_EXCL; *result_pmode = convert_pmode_flags( uiAttr ); HB_TRACE(HB_TR_INFO, ("convert_create_flags: 0x%04x, 0x%04x\n", *result_flags, *result_pmode)); } static int convert_seek_flags( USHORT uiFlags ) { /* by default FS_SET is set */ int result_flags = SEEK_SET; HB_TRACE(HB_TR_DEBUG, ("convert_seek_flags(%hu)", uiFlags)); if( uiFlags & FS_RELATIVE ) result_flags = SEEK_CUR; if( uiFlags & FS_END ) result_flags = SEEK_END; return result_flags; } #endif /* Convert file and dir case. The allowed SET options are: LOWER - Convert all caracters of file to lower UPPER - Convert all caracters of file to upper MIXED - Leave as is The allowed environment options are: FILECASE - define the case of file DIRCASE - define the case of path DIRSEPARATOR - define separator of path (Ex. "/") */ BYTE * hb_filecase( char * str ) { char * filename; char * dirname = str; size_t dirlen; /* Look for filename (Last "\" or DIRSEPARATOR) */ if( hb_set.HB_SET_DIRSEPARATOR != '\\' ) { char * strbak = str; while( *strbak ) { if( *strbak == '\\' ) *strbak = hb_set.HB_SET_DIRSEPARATOR; strbak++; } } if( ( filename = strrchr( str, hb_set.HB_SET_DIRSEPARATOR ) ) != NULL ) filename++; else filename = str; dirlen = filename - str; /* FILECASE */ if( hb_set.HB_SET_FILECASE == HB_SET_CASE_LOWER ) hb_strLower( filename, strlen( filename ) ); else if( hb_set.HB_SET_FILECASE == HB_SET_CASE_UPPER ) hb_strUpper( filename, strlen( filename ) ); /* DIRCASE */ if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_LOWER ) hb_strLower( dirname, dirlen ); else if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_UPPER ) hb_strUpper( dirname, dirlen ); return ( BYTE * ) str; } /* * FILESYS.API FUNCTIONS -- */ FHANDLE hb_fsPOpen( BYTE * pFilename, BYTE * pMode ) { FHANDLE hFileHandle = FS_ERROR; HB_TRACE(HB_TR_DEBUG, ("hb_fsPOpen(%p, %s)", pFilename, pMode)); #if defined(OS_UNIX_COMPATIBLE) { FHANDLE hPipeHandle[2], hNullHandle; pid_t pid; BYTE * pbyTmp; BOOL bRead; ULONG ulLen; int iMaxFD; ulLen = strlen( pFilename ); if( pMode && ( *pMode == 'r' || *pMode == 'w' ) ) bRead = ( *pMode == 'r' ); else { if( pFilename[0] == '|' ) bRead = FALSE; else if( pFilename[ ulLen - 1 ] == '|' ) bRead = TRUE; else bRead = FALSE; } if( pFilename[0] == '|' ) { ++pFilename; --ulLen; } if( pFilename[ ulLen - 1 ] == '|' ) { pbyTmp = hb_strdup( pFilename ); pbyTmp[--ulLen] = 0; pFilename = pbyTmp; } else pbyTmp = NULL; if( pipe( hPipeHandle ) == 0 ) { if( ( pid = fork() ) != -1 ) { if( pid != 0 ) { if( bRead ) { close( hPipeHandle[ 1 ] ); hFileHandle = hPipeHandle[ 0 ]; } else { close( hPipeHandle[ 0 ] ); hFileHandle = hPipeHandle[ 1 ]; } } else { char *argv[4]; argv[0] = "sh"; argv[1] = "-c"; argv[2] = ( char * ) pFilename; argv[3] = ( char * ) 0; hNullHandle = open("/dev/null", O_RDWR); if( bRead ) { close( hPipeHandle[ 0 ] ); dup2( hPipeHandle[ 1 ], 1 ); dup2( hNullHandle, 0 ); dup2( hNullHandle, 2 ); } else { close( hPipeHandle[ 1 ] ); dup2( hPipeHandle[ 0 ], 0 ); dup2( hNullHandle, 1 ); dup2( hNullHandle, 2 ); } iMaxFD = sysconf( _SC_OPEN_MAX ); if ( iMaxFD < 3 ) iMaxFD = 1024; for( hNullHandle = 3; hNullHandle < iMaxFD; ++hNullHandle ) close(hNullHandle); setuid(getuid()); setgid(getgid()); execve("/bin/sh", argv, environ); exit(1); } } else { close( hPipeHandle[0] ); close( hPipeHandle[1] ); } } s_uiErrorLast = hFileHandle != FS_ERROR ? 0 : errno; if( pbyTmp ) hb_xfree( pbyTmp ); } #else HB_SYMBOL_UNUSED( pFilename ); HB_SYMBOL_UNUSED( pMode ); s_uiErrorLast = FS_ERROR; #endif return hFileHandle; } FHANDLE HB_EXPORT hb_fsOpen( BYTE * pFilename, USHORT uiFlags ) { FHANDLE hFileHandle; HB_TRACE(HB_TR_DEBUG, ("hb_fsOpen(%p, %hu)", pFilename, uiFlags)); pFilename = hb_filecase( hb_strdup( ( char * ) pFilename ) ); #if defined(X__WIN32__) { DWORD dwFlags = 0; DWORD dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE; HANDLE hFile; /* read & write flags */ switch( uiFlags & 3) { case FO_READWRITE : dwFlags |= GENERIC_READ | GENERIC_WRITE; break; case FO_WRITE: dwFlags |= GENERIC_WRITE; break; case FO_READ : dwFlags |= GENERIC_READ; break; } /* shared flags */ switch (uiFlags & ( FO_DENYREAD | FO_DENYWRITE | FO_EXCLUSIVE | FO_DENYNONE ) ) { case FO_DENYREAD : dwShare = FILE_SHARE_WRITE; break; case FO_DENYWRITE : dwShare = FILE_SHARE_READ; break; case FO_EXCLUSIVE: dwShare = 0; break; } errno = 0; hFile = ( HANDLE ) CreateFile( ( char * ) pFilename, dwFlags, dwShare, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile == ( HANDLE ) INVALID_HANDLE_VALUE ) #if !defined(__BORLANDC__) errno=WintoDosError(GetLastError()); #else __NTerror(); #endif /* errno = GetLastError(); */ hFileHandle=HandleToLong(hFile); s_uiErrorLast = errno; } #elif defined(HAVE_POSIX_IO) && ! defined(__IBMCPP__) && ! defined(_MSC_VER) hFileHandle = open( ( char * ) pFilename, convert_open_flags( uiFlags ), convert_pmode_flags( 0 ) ); s_uiErrorLast = hFileHandle != FS_ERROR ? 0 : errno; #elif defined(_MSC_VER) { int iShare = _SH_DENYNO; if( ( uiFlags & FO_DENYREAD ) == FO_DENYREAD ) iShare = _SH_DENYRD; else if( uiFlags & FO_EXCLUSIVE ) iShare = _SH_DENYRW; else if( uiFlags & FO_DENYWRITE ) iShare = _SH_DENYWR; errno = 0; if( iShare ) hFileHandle = _sopen( ( char * ) pFilename, convert_open_flags( uiFlags ), iShare ); else hFileHandle = _open( ( char * ) pFilename, convert_open_flags( uiFlags ) ); s_uiErrorLast = errno; } #elif defined(__MINGW32__) || defined(__IBMCPP__) { int iShare = SH_DENYNO; if( ( uiFlags & FO_DENYREAD ) == FO_DENYREAD ) iShare = SH_DENYRD; else if( uiFlags & FO_EXCLUSIVE ) iShare = SH_DENYRW; else if( uiFlags & FO_DENYWRITE ) iShare = SH_DENYWR; if( iShare ) hFileHandle = sopen( ( char * ) pFilename, convert_open_flags( uiFlags ), iShare ); else hFileHandle = open( ( char * ) pFilename, convert_open_flags( uiFlags ) ); s_uiErrorLast = hFileHandle != FS_ERROR ? 0 : errno; } #else hFileHandle = FS_ERROR; s_uiErrorLast = FS_ERROR; #endif hb_xfree( pFilename ); return hFileHandle; } FHANDLE HB_EXPORT hb_fsCreate( BYTE * pFilename, USHORT uiAttr ) { FHANDLE hFileHandle; int oflag; unsigned pmode; HB_TRACE(HB_TR_DEBUG, ("hb_fsCreate(%p, %hu)", pFilename, uiAttr)); pFilename = hb_filecase( hb_strdup( ( char * ) pFilename ) ); s_uiErrorLast = 0; #if defined(X__WIN32__) { DWORD dwFlags = FILE_ATTRIBUTE_ARCHIVE; HANDLE hFile; if( uiAttr & FC_READONLY ) dwFlags |= FILE_ATTRIBUTE_READONLY; if( uiAttr & FC_HIDDEN ) dwFlags |= FILE_ATTRIBUTE_HIDDEN; if( uiAttr & FC_SYSTEM ) dwFlags |= FILE_ATTRIBUTE_SYSTEM; errno = 0; hFile = ( HANDLE ) CreateFile( ( char * ) pFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, dwFlags, NULL ); if( hFile == ( HANDLE ) INVALID_HANDLE_VALUE ) errno = GetLastError(); hFileHandle=HandleToLong(hFile); s_uiErrorLast = errno; } #elif defined(HB_FS_FILE_IO) convert_create_flags( uiAttr, &oflag, &pmode ); hFileHandle = open( ( char * ) pFilename, oflag, pmode ); s_uiErrorLast = hFileHandle != FS_ERROR ? 0 : errno; #else hFileHandle = FS_ERROR; s_uiErrorLast = FS_ERROR; #endif hb_xfree( pFilename ); return hFileHandle; } /* Derived from hb_fsCreate() NOTE: The default opening mode differs from the one used in hb_fsCreate() [vszakats] */ FHANDLE HB_EXPORT hb_fsCreateEx( BYTE * pFilename, USHORT uiAttr, USHORT uiFlags ) { FHANDLE hFileHandle; int oflag; unsigned pmode; HB_TRACE(HB_TR_DEBUG, ("hb_fsCreateEx(%p, %hu, %hu)", pFilename, uiAttr, uiFlags)); pFilename = hb_filecase( hb_strdup( ( char * ) pFilename ) ); s_uiErrorLast = 0; #if defined(HB_FS_FILE_IO) convert_create_flags_ex( uiAttr, uiFlags, &oflag, &pmode ); hFileHandle = open( ( char * ) pFilename, oflag, pmode ); s_uiErrorLast = hFileHandle != FS_ERROR ? 0 : errno; #else hFileHandle = FS_ERROR; s_uiErrorLast = FS_ERROR; #endif hb_xfree( pFilename ); return hFileHandle; } void HB_EXPORT hb_fsClose( FHANDLE hFileHandle ) { HB_TRACE(HB_TR_DEBUG, ("hb_fsClose(%p)", hFileHandle)); #if defined(HB_FS_FILE_IO) errno = 0; #if defined(X__WIN32__) if( ! CloseHandle( DostoWinHandle( hFileHandle ) ) ) { #if !defined(__BORLANDC__) errno = WintoDosError( GetLastError() ); #else __NTerror(); #endif } #else close( hFileHandle ); #endif s_uiErrorLast = errno; #else s_uiErrorLast = FS_ERROR; #endif /* Convert 'Invalid Memory Block' to 'Invalid Handle' */ if( s_uiErrorLast == 9 ) s_uiErrorLast = 6; } BOOL hb_fsSetDevMode( FHANDLE hFileHandle, USHORT uiDevMode ) { BOOL bResult; HB_TRACE(HB_TR_DEBUG, ("hb_fsSetDevMode(%p, %hu)", hFileHandle, uiDevMode)); #if defined(__BORLANDC__) || defined(__IBMCPP__) || defined(__DJGPP__) || defined(__CYGWIN__) || defined(__WATCOMC__) errno = 0; switch( uiDevMode ) { case FD_BINARY: bResult = ( setmode( hFileHandle, O_BINARY ) != -1 ); break; case FD_TEXT: bResult = ( setmode( hFileHandle, O_TEXT ) != -1 ); break; default: bResult = FALSE; } s_uiErrorLast = errno; #elif defined(_MSC_VER) || defined(__MINGW32__) errno = 0; switch( uiDevMode ) { case FD_BINARY: bResult = ( _setmode( hFileHandle, _O_BINARY ) != -1 ); break; case FD_TEXT: bResult = ( _setmode( hFileHandle, _O_TEXT ) != -1 ); break; default: bResult = FALSE; } s_uiErrorLast = errno; #else HB_SYMBOL_UNUSED( hFileHandle ); HB_SYMBOL_UNUSED( uiDevMode ); bResult = FALSE; s_uiErrorLast = FS_ERROR; #endif return bResult; } USHORT HB_EXPORT hb_fsRead( FHANDLE hFileHandle, BYTE * pBuff, USHORT uiCount ) { USHORT uiRead; HB_TRACE(HB_TR_DEBUG, ("hb_fsRead(%p, %p, %hu)", hFileHandle, pBuff, uiCount)); #if defined(HB_FS_FILE_IO) errno = 0; #if defined(X__WIN32__) { DWORD dwRead = 0; if( ! ReadFile( DostoWinHandle( hFileHandle ), pBuff, ( DWORD ) uiCount, &dwRead, NULL ) ) errno = GetLastError(); uiRead = ( USHORT ) dwRead; } #else uiRead = read( hFileHandle, pBuff, uiCount ); #endif s_uiErrorLast = errno; if( uiRead == ( USHORT ) -1 ) uiRead = 0; #else uiRead = 0; s_uiErrorLast = FS_ERROR; #endif return uiRead; } USHORT HB_EXPORT hb_fsWrite( FHANDLE hFileHandle, BYTE * pBuff, USHORT uiCount ) { USHORT uiWritten; HB_TRACE(HB_TR_DEBUG, ("hb_fsWrite(%p, %p, %hu)", hFileHandle, pBuff, uiCount)); #if defined(HB_FS_FILE_IO) errno = 0; #if defined(X__WIN32__) { DWORD dwWritten = 0; if( ! WriteFile( DostoWinHandle( hFileHandle ), pBuff, uiCount, &dwWritten, NULL ) ) errno = GetLastError(); uiWritten = ( USHORT ) dwWritten; } #else if( uiCount ) { uiWritten = write( hFileHandle, pBuff, uiCount ); if( uiWritten == ( USHORT ) -1 ) uiWritten = 0; } else { uiWritten = 0; ftruncate( hFileHandle, lseek( hFileHandle, 0L, SEEK_CUR ) ); } s_uiErrorLast = errno; #endif #else uiWritten = 0; s_uiErrorLast = FS_ERROR; #endif return uiWritten; } ULONG HB_EXPORT hb_fsReadLarge( FHANDLE hFileHandle, BYTE * pBuff, ULONG ulCount ) { ULONG ulRead; HB_TRACE(HB_TR_DEBUG, ("hb_fsReadLarge(%p, %p, %lu)", hFileHandle, pBuff, ulCount)); #if defined(HB_FS_FILE_IO) errno = 0; #if defined(X__WIN32__) { if( ! ReadFile( DostoWinHandle( hFileHandle ), pBuff, ulCount, &ulRead, NULL ) ) errno = GetLastError(); } #elif defined(HB_FS_LARGE_OPTIMIZED) ulRead = read( hFileHandle, pBuff, ulCount ); #else { ULONG ulLeftToRead = ulCount; USHORT uiToRead; USHORT uiRead; BYTE * pPtr = pBuff; ulRead = 0; while( ulLeftToRead ) { /* Determine how much to read this time */ if( ulLeftToRead > ( ULONG ) INT_MAX ) { uiToRead = INT_MAX; ulLeftToRead -= ( ULONG ) uiToRead; } else { uiToRead = ( USHORT ) ulLeftToRead; ulLeftToRead = 0; } uiRead = read( hFileHandle, pPtr, uiToRead ); /* -1 on bad hFileHandle 0 on disk full */ if( uiRead == 0 ) break; if( uiRead == ( USHORT ) -1 ) { uiRead = 0; break; } ulRead += ( ULONG ) uiRead; pPtr += uiRead; } } #endif s_uiErrorLast = errno; #else ulRead = 0; s_uiErrorLast = FS_ERROR; #endif return ulRead; } ULONG HB_EXPORT hb_fsWriteLarge( FHANDLE hFileHandle, BYTE * pBuff, ULONG ulCount ) { ULONG ulWritten; HB_TRACE(HB_TR_DEBUG, ("hb_fsWriteLarge(%p, %p, %lu)", hFileHandle, pBuff, ulCount)); #if defined(HB_FS_FILE_IO) errno = 0; #if defined(X__WIN32__) { if( ! WriteFile( DostoWinHandle( hFileHandle), pBuff, ulCount, &ulWritten, NULL ) ) errno = GetLastError(); } #else if( ulCount ) #if defined(HB_FS_LARGE_OPTIMIZED) { ulWritten = write( hFileHandle, pBuff, ulCount ); if( ulWritten == ( ULONG ) -1 ) ulWritten = 0; } #else { ULONG ulLeftToWrite = ulCount; USHORT uiToWrite; USHORT uiWritten; BYTE * pPtr = pBuff; ulWritten = 0; while( ulLeftToWrite ) { /* Determine how much to write this time */ if( ulLeftToWrite > ( ULONG ) INT_MAX ) { uiToWrite = INT_MAX; ulLeftToWrite -= ( ULONG ) uiToWrite; } else { uiToWrite = ( USHORT ) ulLeftToWrite; ulLeftToWrite = 0; } uiWritten = write( hFileHandle, pPtr, uiToWrite ); /* -1 on bad hFileHandle 0 on disk full */ if( uiWritten == 0 ) break; if( uiWritten == ( USHORT ) -1 ) { uiWritten = 0; break; } ulWritten += ( ULONG ) uiWritten; pPtr += uiWritten; } } #endif else { ulWritten = 0; ftruncate( hFileHandle, lseek( hFileHandle, 0L, SEEK_CUR ) ); } #endif s_uiErrorLast = errno; #else ulWritten = 0; s_uiErrorLast = FS_ERROR; #endif return ulWritten; } void HB_EXPORT hb_fsCommit( FHANDLE hFileHandle ) { HB_TRACE(HB_TR_DEBUG, ("hb_fsCommit(%p)", hFileHandle)); #if defined(X__WIN32__) FlushFileBuffers( ( HANDLE ) DostoWinHandle( hFileHandle ) ); s_uiErrorLast = ( USHORT ) GetLastError(); #elif defined(HB_OS_OS2) { errno = 0; /* TODO: what about error code from DosResetBuffer() call? */ DosResetBuffer( hFileHandle ); s_uiErrorLast = errno; } #elif defined(HB_OS_UNIX) /* NOTE: close() functions releases all lock regardles if it is an * original or duplicated file handle */ #if defined(_POSIX_SYNCHRONIZED_IO) && (_POSIX_SYNCHRONIZED_IO > 0) /* faster - flushes data buffers only, without updating directory info */ s_uiErrorLast = ( fdatasync( hFileHandle ) < -1 ) ? FS_ERROR : 0; if( s_uiErrorLast == EINVAL ) { /* This implementation does not support synchronised I/O for this file, so use the slower method that flushes all file data buffers and i-node info for this file. */ s_uiErrorLast = ( fsync( hFileHandle ) < -1 ) ? FS_ERROR : 0; } #else /* slower - flushes all file data buffers and i-node info */ s_uiErrorLast = ( fsync( hFileHandle ) < -1 ) ? FS_ERROR : 0; #endif #elif defined(__WATCOMC__) _dos_commit( hFileHandle ); #elif defined(HB_FS_FILE_IO) && !defined(HB_OS_OS2) && !defined(HB_OS_UNIX) { int dup_handle; errno = 0; dup_handle = dup( hFileHandle ); if( dup_handle != -1 ) close( dup_handle ); s_uiErrorLast = errno; } #else s_uiErrorLast = FS_ERROR; #endif } BOOL HB_EXPORT hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, ULONG ulLength, USHORT uiMode ) { BOOL bResult; HB_TRACE(HB_TR_DEBUG, ("hb_fsLock(%p, %lu, %lu, %hu)", hFileHandle, ulStart, ulLength, uiMode)); #if defined(X__WIN32__) { errno = 0; switch( uiMode & FL_MASK ) { case FL_LOCK: bResult = ( LockFile( DostoWinHandle(hFileHandle), ulStart,0, ulLength,0 ) == 0 ); break; case FL_UNLOCK: bResult = ( UnlockFile( DostoWinHandle(hFileHandle), ulStart,0, ulLength,0 ) == 0 ); break; default: bResult = FALSE; } s_uiErrorLast = errno; } #elif defined(HB_OS_OS2) { struct _FILELOCK fl, ful; errno = 0; switch( uiMode & FL_MASK ) { case FL_LOCK: fl.lOffset = ulStart; fl.lRange = ulLength; ful.lOffset = 0; ful.lRange = 0; /* lock region, 2 seconds timeout, exclusive access - no atomic */ bResult = ( DosSetFileLocks( hFileHandle, &ful, &fl, 2000L, 0L ) == 0 ); break; case FL_UNLOCK: fl.lOffset = 0; fl.lRange = 0; ful.lOffset = ulStart; ful.lRange = ulLength; /* unlock region, 2 seconds timeout, exclusive access - no atomic */ bResult = ( DosSetFileLocks( hFileHandle, &ful, &fl, 2000L, 0L ) == 0 ); break; default: bResult = FALSE; } s_uiErrorLast = errno; } #elif defined(_MSC_VER) { ULONG ulOldPos = hb_fsSeek( hFileHandle, ulStart, FS_SET ); errno = 0; switch( uiMode & FL_MASK ) { case FL_LOCK: bResult = ( locking( hFileHandle, _LK_LOCK, ulLength ) == 0 ); break; case FL_UNLOCK: bResult = ( locking( hFileHandle, _LK_UNLCK, ulLength ) == 0 ); break; default: bResult = FALSE; } s_uiErrorLast = errno; hb_fsSeek( hFileHandle, ulOldPos, FS_SET ); } #elif defined(__MINGW32__) { ULONG ulOldPos = hb_fsSeek( hFileHandle, ulStart, FS_SET ); errno = 0; switch( uiMode & FL_MASK ) { case FL_LOCK: bResult = ( _locking( hFileHandle, _LK_LOCK, ulLength ) == 0 ); break; case FL_UNLOCK: bResult = ( _locking( hFileHandle, _LK_UNLCK, ulLength ) == 0 ); break; default: bResult = FALSE; } s_uiErrorLast = errno; hb_fsSeek( hFileHandle, ulOldPos, FS_SET ); } #elif defined(__GNUC__) && defined(HB_OS_UNIX) { /* TODO: check for append locks (SEEK_END) */ struct flock lock_info; switch( uiMode & FL_MASK ) { case FL_LOCK: lock_info.l_type = (uiMode & FLX_SHARED) ? F_RDLCK : F_WRLCK; 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(); bResult = ( fcntl( hFileHandle, (uiMode & FLX_WAIT) ? F_SETLKW: F_SETLK, &lock_info ) >= 0 ); break; case FL_UNLOCK: lock_info.l_type = F_UNLCK; /* unlock */ lock_info.l_start = ulStart; lock_info.l_len = ulLength; lock_info.l_whence = SEEK_SET; lock_info.l_pid = getpid(); bResult = ( fcntl( hFileHandle, F_SETLK, &lock_info ) >= 0 ); break; default: bResult = FALSE; } s_uiErrorLast = bResult ? 0 : errno; } #elif defined(HAVE_POSIX_IO) && !defined(__IBMCPP__) && ( !defined(__GNUC__) || defined(__DJGPP__) ) errno = 0; switch( uiMode & FL_MASK ) { case FL_LOCK: bResult = ( lock( hFileHandle, ulStart, ulLength ) == 0 ); break; case FL_UNLOCK: bResult = ( unlock( hFileHandle, ulStart, ulLength ) == 0 ); break; default: bResult = FALSE; } s_uiErrorLast = errno; #else bResult = FALSE; s_uiErrorLast = FS_ERROR; #endif return bResult; } BOOL HB_EXPORT hb_fsLockLarge( FHANDLE hFileHandle, HB_FOFFSET ulStart, HB_FOFFSET ulLength, USHORT uiMode ) { BOOL bResult; HB_TRACE(HB_TR_DEBUG, ("hb_fsLockLarge(%p, %" PFHL "u, %" PFHL "u, %hu)", hFileHandle, ulStart, ulLength, uiMode)); #if defined(HB_FS_FILE_IO) && defined(HB_OS_LINUX) && \ defined(__USE_LARGEFILE64) /* * The macro: __USE_LARGEFILE64 is set when _LARGEFILE64_SOURCE is * define and efectively enables lseek64/flock64 functions on 32bit * machines. */ { struct flock64 lock_info; switch( uiMode & FL_MASK ) { case FL_LOCK: lock_info.l_type = (uiMode & FLX_SHARED) ? F_RDLCK : F_WRLCK; 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(); bResult = ( fcntl( hFileHandle, (uiMode & FLX_WAIT) ? F_SETLKW64: F_SETLK64, &lock_info ) != -1 ); break; case FL_UNLOCK: lock_info.l_type = F_UNLCK; /* unlock */ lock_info.l_start = ulStart; lock_info.l_len = ulLength; lock_info.l_whence = SEEK_SET; lock_info.l_pid = getpid(); bResult = ( fcntl( hFileHandle, F_SETLK64, &lock_info ) != -1 ); break; default: bResult = FALSE; } s_uiErrorLast = bResult ? 0 : errno; } #else bResult = hb_fsLock( hFileHandle, (ULONG) ulStart, (ULONG) ulLength, uiMode ); #endif return bResult; } ULONG HB_EXPORT hb_fsSeek( FHANDLE hFileHandle, LONG lOffset, USHORT uiFlags ) { ULONG ulPos; USHORT Flags; HB_TRACE(HB_TR_DEBUG, ("hb_fsSeek(%p, %ld, %hu)", hFileHandle, lOffset, uiFlags)); Flags = convert_seek_flags( uiFlags ); if( lOffset < 0 && Flags == SEEK_SET ) { #if defined(HB_OS_OS2) { APIRET ret = DosSetFilePtr( hFileHandle, 0, SEEK_CUR, &ulPos ); if( ret != 0 ) { ulPos = 0; s_uiErrorLast = ( USHORT ) ret; } } #elif defined(HB_FS_FILE_IO) /* get current offset */ errno = 0; #if defined(X__WIN32__) ulPos = SetFilePointer( DostoWinHandle( hFileHandle ), 0, NULL, FILE_CURRENT ); if( ( DWORD ) ulPos == 0xFFFFFFFF ) errno = GetLastError(); #else ulPos = lseek( hFileHandle, 0, SEEK_CUR ); #endif if( errno != 0 ) { ulPos = 0; s_uiErrorLast = errno; } else s_uiErrorLast = 25; /* 'Seek Error' */ #else ulPos = 0; s_uiErrorLast = 25; /* 'Seek Error' */ #endif } else { #if defined(HB_OS_OS2) { APIRET ret = DosSetFilePtr( hFileHandle, lOffset, Flags, &ulPos ); if( ret != 0 ) { ulPos = 0; s_uiErrorLast = ( USHORT ) ret; } } #elif defined(HB_FS_FILE_IO) errno = 0; #if defined(X__WIN32__) ulPos = SetFilePointer( DostoWinHandle( hFileHandle ), lOffset, NULL, ( DWORD ) Flags ); if( ( DWORD ) ulPos == 0xFFFFFFFF ) errno = GetLastError(); #else ulPos = lseek( hFileHandle, lOffset, Flags ); #endif if( errno != 0 ) ulPos = 0; s_uiErrorLast = errno; #else ulPos = 0; s_uiErrorLast = FS_ERROR; #endif /* Convert 'Unknown Command' to 'Seek Error' */ if( s_uiErrorLast == 22 ) s_uiErrorLast = 25; } return ulPos; } HB_FOFFSET HB_EXPORT hb_fsSeekLarge( FHANDLE hFileHandle, HB_FOFFSET llOffset, USHORT uiFlags ) { HB_FOFFSET llPos; HB_TRACE(HB_TR_DEBUG, ("hb_fsSeekLarge(%p, %" PFHL "u, %hu)", hFileHandle, llOffset, uiFlags)); #if defined(HB_FS_FILE_IO) && defined(HB_OS_LINUX) && \ defined(__USE_LARGEFILE64) /* * The macro: __USE_LARGEFILE64 is set when _LARGEFILE64_SOURCE is * define and efectively enables lseek64/flock64 functions on 32bit * machines. */ { USHORT Flags = convert_seek_flags( uiFlags ); llPos = lseek64( hFileHandle, llOffset, Flags ); s_uiErrorLast = ( llPos != (HB_FOFFSET) -1 ? 0 : errno ); if ( llPos == (HB_FOFFSET) -1 ) { llPos = lseek64( hFileHandle, 0L, SEEK_CUR ); } } #else llPos = (HB_FOFFSET) hb_fsSeek( hFileHandle, (LONG) llOffset, uiFlags ); #endif return llPos; } ULONG HB_EXPORT hb_fsTell( FHANDLE hFileHandle ) { ULONG ulPos; HB_TRACE(HB_TR_DEBUG, ("hb_fsTell(%p)", hFileHandle)); #if defined(HB_FS_FILE_IO) errno = 0; #if defined(X__WIN32__) ulPos = SetFilePointer( DostoWinHandle( hFileHandle ), 0, NULL, FILE_CURRENT ); if( ( DWORD ) ulPos == 0xFFFFFFFF ) errno = GetLastError(); #else ulPos = lseek( hFileHandle, 0L, SEEK_CUR ); #endif s_uiErrorLast = errno; #else ulPos = 0; s_uiErrorLast = FS_ERROR; #endif return ulPos; } USHORT HB_EXPORT hb_fsError( void ) { HB_TRACE(HB_TR_DEBUG, ("hb_fsError()")); return s_uiErrorLast; } void hb_fsSetError( USHORT uiError ) { HB_TRACE(HB_TR_DEBUG, ("hb_fsSetError(%hu)", uiError)); s_uiErrorLast = uiError; } BOOL HB_EXPORT hb_fsDelete( BYTE * pFilename ) { BOOL bResult; HB_TRACE(HB_TR_DEBUG, ("hb_fsDelete(%s)", (char*) pFilename)); #if defined(X__WIN32__) if( ( bResult = DeleteFile( ( char * ) pFilename ) ) == 0 ) { #if !defined(__BORLANDC__) errno = WintoDosError( GetLastError() ); #else __NTerror(); #endif } s_uiErrorLast = errno; #elif defined(HAVE_POSIX_IO) errno = 0; bResult = ( unlink( ( char * ) pFilename ) == 0 ); s_uiErrorLast = errno; #elif defined(_MSC_VER) || defined(__MINGW32__) errno = 0; bResult = ( remove( ( char * ) pFilename ) == 0 ); s_uiErrorLast = errno; #else bResult = FALSE; s_uiErrorLast = FS_ERROR; #endif return bResult; } BOOL HB_EXPORT hb_fsRename( BYTE * pOldName, BYTE * pNewName ) { BOOL bResult; HB_TRACE(HB_TR_DEBUG, ("hb_fsRename(%s, %s)", (char*) pOldName, (char*) pNewName)); #if defined(X__WIN32__) errno = 0; if( ( bResult = MoveFile( ( char * ) pOldName, ( char * ) pNewName ) ) == 0 ) { #if !defined(__BORLANDC__) errno = WintoDosError( GetLastError() ); #else __NTerror(); #endif } s_uiErrorLast = errno; #elif defined(HB_FS_FILE_IO) errno = 0; bResult = ( rename( ( char * ) pOldName, ( char * ) pNewName ) == 0 ); s_uiErrorLast = errno; #else bResult = FALSE; s_uiErrorLast = FS_ERROR; #endif return bResult; } BOOL HB_EXPORT hb_fsMkDir( BYTE * pDirname ) { BOOL bResult; HB_TRACE(HB_TR_DEBUG, ("hb_fsMkDir(%s)", (char*) pDirname)); pDirname = ( BYTE * ) hb_strdup ( ( char * ) pDirname ); if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_LOWER ) pDirname = ( BYTE * ) hb_strLower( ( char *) pDirname, strlen( ( char *) pDirname ) ); else if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_UPPER) pDirname = ( BYTE * ) hb_strUpper( ( char *) pDirname, strlen( ( char *) pDirname ) ); #if defined(HB_OS_WIN_32) bResult = CreateDirectory( ( char * ) pDirname, NULL ); s_uiErrorLast = ( USHORT ) GetLastError(); #elif defined(HAVE_POSIX_IO) || defined(__MINGW32__) errno = 0; #if !defined(__WATCOMC__) && !defined(__BORLANDC__) && !defined(__IBMCPP__) && !defined(__MINGW32__) bResult = ( mkdir( ( char * ) pDirname, S_IWUSR | S_IRUSR | S_IXUSR ) == 0 ); #else bResult = ( mkdir( ( char * ) pDirname ) == 0 ); #endif s_uiErrorLast = errno; #else bResult = FALSE; s_uiErrorLast = FS_ERROR; #endif hb_xfree( pDirname ); return bResult; } BOOL HB_EXPORT hb_fsChDir( BYTE * pDirname ) { BOOL bResult; HB_TRACE(HB_TR_DEBUG, ("hb_fsChDir(%s)", (char*) pDirname)); pDirname = ( BYTE *) hb_strdup ( ( char * ) pDirname ); if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_LOWER ) pDirname = ( BYTE * ) hb_strLower( ( char *) pDirname, strlen( ( char *) pDirname ) ); else if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_UPPER) pDirname = ( BYTE * ) hb_strUpper( ( char *) pDirname, strlen( ( char *) pDirname ) ); #if defined(HB_OS_WIN_32) bResult = SetCurrentDirectory( ( char * ) pDirname ); s_uiErrorLast = ( USHORT ) GetLastError(); #elif defined(HAVE_POSIX_IO) || defined(__MINGW32__) errno = 0; bResult = ( chdir( ( char * ) pDirname ) == 0 ); s_uiErrorLast = errno; #else bResult = FALSE; s_uiErrorLast = FS_ERROR; #endif hb_xfree( pDirname ); return bResult; } BOOL HB_EXPORT hb_fsRmDir( BYTE * pDirname ) { BOOL bResult; HB_TRACE(HB_TR_DEBUG, ("hb_fsRmDir(%s)", (char*) pDirname)); pDirname = ( BYTE * ) hb_strdup ( ( char * ) pDirname ); if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_LOWER ) pDirname = ( BYTE * ) hb_strLower( ( char *) pDirname, strlen( ( char *) pDirname ) ); else if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_UPPER) pDirname = ( BYTE * ) hb_strUpper( ( char *) pDirname, strlen( ( char *) pDirname ) ); #if defined(HB_OS_WIN_32) bResult = RemoveDirectory( ( char * ) pDirname ); s_uiErrorLast = ( USHORT ) GetLastError(); #elif defined(HAVE_POSIX_IO) || defined(__MINGW32__) errno = 0; bResult = ( rmdir( ( char * ) pDirname ) == 0 ); s_uiErrorLast = errno; #else bResult = FALSE; s_uiErrorLast = FS_ERROR; #endif hb_xfree( pDirname ); return bResult; } /* NOTE: This is not thread safe function, it's there for compatibility. */ /* NOTE: 0 = current drive, 1 = A, 2 = B, 3 = C, etc. */ BYTE * HB_EXPORT hb_fsCurDir( USHORT uiDrive ) { static BYTE s_byDirBuffer[ _POSIX_PATH_MAX + 1 ]; HB_TRACE(HB_TR_DEBUG, ("hb_fsCurDir(%hu)", uiDrive)); hb_fsCurDirBuff( uiDrive, s_byDirBuffer, _POSIX_PATH_MAX + 1 ); return ( BYTE * ) s_byDirBuffer; } /* NOTE: Thread safe version of hb_fsCurDir() */ /* NOTE: 0 = current drive, 1 = A, 2 = B, 3 = C, etc. */ USHORT HB_EXPORT hb_fsCurDirBuff( USHORT uiDrive, BYTE * pbyBuffer, ULONG ulLen ) { HB_TRACE(HB_TR_DEBUG, ("hb_fsCurDirBuff(%hu)", uiDrive)); HB_SYMBOL_UNUSED( uiDrive ); pbyBuffer[ 0 ] = '\0'; #if defined(HB_OS_WIN_32) GetCurrentDirectory( ulLen, ( char * ) pbyBuffer ); s_uiErrorLast = ( USHORT ) GetLastError(); #elif defined(HAVE_POSIX_IO) errno = 0; getcwd( ( char * ) pbyBuffer, ulLen ); s_uiErrorLast = errno; #elif defined(__MINGW32__) errno = 0; _getdcwd( uiDrive, pbyBuffer, ulLen ); s_uiErrorLast = errno; #else s_uiErrorLast = FS_ERROR; #endif /* Strip the leading drive spec, and leading backslash if there's one. */ { BYTE * pbyStart = pbyBuffer; /* NOTE: A trailing underscore is not returned on this platform, so we don't need to strip it. [vszakats] */ if( pbyStart[ 1 ] == ':' ) { pbyStart += 2; ulLen -= 2; } if( strchr( OS_PATH_DELIMITER_LIST, pbyStart[ 0 ] ) ) { pbyStart++; ulLen--; } if( pbyBuffer != pbyStart ) memmove( pbyBuffer, pbyStart, ulLen ); } /* Strip the trailing (back)slash if there's one */ { ULONG ulLen = strlen( ( char * ) pbyBuffer ); if( strchr( OS_PATH_DELIMITER_LIST, pbyBuffer[ ulLen - 1 ] ) ) pbyBuffer[ ulLen - 1 ] = '\0'; } return s_uiErrorLast; } /* NOTE: 0=A:, 1=B:, 2=C:, 3=D:, ... */ USHORT HB_EXPORT hb_fsChDrv( BYTE nDrive ) { USHORT uiResult; HB_TRACE(HB_TR_DEBUG, ("hb_fsChDrv(%d)", (int) nDrive)); #if defined(HB_FS_DRIVE_LETTER) #if defined( __WATCOMC__ ) { /* 'unsigned int' _have to_ be used in Watcom */ unsigned int uiSave; unsigned int uiTotal; /* 1 = A:, 2 = B:, 3 = C:, etc * _dos_*() functions don't set 'errno' */ _dos_getdrive( &uiSave ); _dos_setdrive( nDrive + 1, &uiTotal ); _dos_getdrive( &uiTotal ); if( ( nDrive + 1 ) == uiTotal ) { uiResult = 0; s_uiErrorLast = 0; } else { _dos_setdrive( uiSave, &uiTotal ); uiResult = FS_ERROR; s_uiErrorLast = FS_ERROR; } } #else { USHORT uiSave = _getdrive(); errno = 0; _chdrive( nDrive + 1 ); if( ( nDrive + 1 ) == _getdrive() ) { uiResult = 0; s_uiErrorLast = errno; } else { _chdrive( uiSave ); uiResult = FS_ERROR; s_uiErrorLast = FS_ERROR; } } #endif #else HB_SYMBOL_UNUSED( nDrive ); uiResult = FS_ERROR; s_uiErrorLast = FS_ERROR; #endif return uiResult; } /* NOTE: 0=A:, 1=B:, 2=C:, 3=D:, ... */ /* TOFIX: This isn't fully compliant because CA-Cl*pper doesn't access the drive before checking. hb_fsIsDrv only returns TRUE if there is a disk in the drive. */ USHORT HB_EXPORT hb_fsIsDrv( BYTE nDrive ) { USHORT uiResult; HB_TRACE(HB_TR_DEBUG, ("hb_fsIsDrv(%d)", (int) nDrive)); #if defined(HB_FS_DRIVE_LETTER) #if defined( __WATCOMC__ ) { /* 'unsigned int' _have to_ be used in Watcom */ unsigned int uiSave; unsigned int uiTotal; /* 1= A:, 2 = B:, 3 = C:, etc * _dos_*() functions don't set 'errno' */ _dos_getdrive( &uiSave ); s_uiErrorLast = 0; uiResult = 0; _dos_setdrive( nDrive + 1, &uiTotal ); _dos_getdrive( &uiTotal ); if( ( nDrive + 1 ) != uiTotal ) { s_uiErrorLast = FS_ERROR; uiResult = FS_ERROR; } _dos_setdrive( uiSave, &uiTotal ); } #else { USHORT uiSave = _getdrive(); errno = 0; _chdrive( nDrive + 1 ); if( ( nDrive + 1 ) == _getdrive() ) { uiResult = 0; s_uiErrorLast = errno; } else { uiResult = FS_ERROR; s_uiErrorLast = FS_ERROR; } _chdrive( uiSave ); } #endif #else HB_SYMBOL_UNUSED( nDrive ); uiResult = FS_ERROR; s_uiErrorLast = FS_ERROR; #endif return uiResult; } BOOL HB_EXPORT hb_fsIsDevice( FHANDLE hFileHandle ) { BOOL bResult; HB_TRACE(HB_TR_DEBUG, ("hb_fsIsDevice(%p)", hFileHandle)); #if defined(HB_FS_DRIVE_LETTER) errno = 0; bResult = ( isatty( hFileHandle ) == 0 ); s_uiErrorLast = errno; #else bResult = FALSE; s_uiErrorLast = FS_ERROR; HB_SYMBOL_UNUSED( hFileHandle ); #endif return bResult; } /* NOTE: 0=A:, 1=B:, 2=C:, 3=D:, ... */ BYTE HB_EXPORT hb_fsCurDrv( void ) { USHORT uiResult; HB_TRACE(HB_TR_DEBUG, ("hb_fsCurDrv()")); #if defined(HB_FS_DRIVE_LETTER) { errno = 0; uiResult = _getdrive(); #if defined(__DJGPP__) /* _getdrive() returned a drive number, base 0. */ #else if( uiResult < 65 ) { /* _getdrive() returned a drive number, base 1. */ uiResult--; } else { /* _getdrive() returned a drive letter. */ uiResult -= 65; } #endif s_uiErrorLast = errno; } #elif defined( __WATCOMC__ ) { /* 'unsigned int' _have to_ be used in Watcom */ unsigned uiDrive; /* 1 = A:, 2 = B:, 3 = C:, etc * _dos_*() functions don't set 'errno' */ _dos_getdrive( &uiDrive ); s_uiErrorLast = 0; uiResult = ( USHORT ) uiDrive - 1; } #else uiResult = 0; s_uiErrorLast = FS_ERROR; #endif return ( BYTE ) uiResult; /* Return the drive number, base 0. */ } /* TODO: Implement hb_fsExtOpen */ FHANDLE hb_fsExtOpen( BYTE * pFilename, BYTE * pDefExt, USHORT uiFlags, BYTE * pPaths, PHB_ITEM pError ) { HB_TRACE(HB_TR_DEBUG, ("hb_fsExtOpen(%s, %s, %hu, %p, %p)", (char*) pFilename, (char*) pDefExt, uiFlags, pPaths, pError)); s_uiErrorLast = FS_ERROR; HB_SYMBOL_UNUSED( pFilename ); HB_SYMBOL_UNUSED( pDefExt ); HB_SYMBOL_UNUSED( uiFlags ); HB_SYMBOL_UNUSED( pPaths ); HB_SYMBOL_UNUSED( pError ); return s_uiErrorLast; } BOOL hb_fsEof( FHANDLE hFileHandle ) { #if defined(__DJGPP__) || defined(__CYGWIN__) || defined(OS_UNIX_COMPATIBLE) long curPos = lseek( hFileHandle, 0L, SEEK_CUR ); long endPos = lseek( hFileHandle, 0L, SEEK_END ); long newPos = lseek( hFileHandle, curPos, SEEK_SET ); if( newPos == -1L ) { hb_fsSetError( errno ); } else if( newPos != curPos ) { hb_fsSetError( FS_ERROR ); } return curPos >= endPos; #else return eof( hFileHandle ) != 0; #endif } #if defined(X__WIN32__) static HANDLE DostoWinHandle( FHANDLE fHandle) { switch( fHandle ) { case 0: return GetStdHandle(STD_INPUT_HANDLE); case 1: return GetStdHandle(STD_OUTPUT_HANDLE); case 2: return GetStdHandle(STD_ERROR_HANDLE); default : return LongToHandle( fHandle ); } } #endif BYTE HB_EXPORT * hb_fileNameConv(char *str) { /* Convert file and dir case. The allowed SET options are: LOWER - Convert all caracters of file to lower UPPER - Convert all caracters of file to upper MIXED - Leave as is The allowed environment options are: FILECASE - define the case of file DIRCASE - define the case of path DIRSEPARATOR - define separator of path (Ex. "/") */ size_t a; char *filename; char *dirname=str; size_t dirlen; /* char * szFileTrim =str; */ /* Look for filename (Last "\" or DIRSEPARATOR) */ if( hb_set.HB_SET_DIRSEPARATOR != '\\' ) { for(a=0;a