Files
harbour-core/harbour/source/rtl/filesys.c
Przemyslaw Czerpak 78070e00c4 2004-12-31 12:35 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbapicdp.h
  * harbour/source/codepage/cdp_tpl.c
  * harbour/source/codepage/cdpeldos.c
  * harbour/source/codepage/cdpelwin.c
  * harbour/source/codepage/cdpesdos.c
  * harbour/source/codepage/cdpeswin.c
  * harbour/source/codepage/cdpgedos.c
  * harbour/source/codepage/cdpgewin.c
  * harbour/source/codepage/cdphu852.c
  * harbour/source/codepage/cdphuwin.c
  * harbour/source/codepage/cdppl852.c
  * harbour/source/codepage/cdppliso.c
  * harbour/source/codepage/cdpplmaz.c
  * harbour/source/codepage/cdpplwin.c
  * harbour/source/codepage/cdppt850.c
  * harbour/source/codepage/cdpptiso.c
  * harbour/source/codepage/cdpru866.c
  * harbour/source/codepage/cdprukoi.c
  * harbour/source/codepage/cdpruwin.c
  * harbour/source/codepage/cdpsl437.c
  * harbour/source/codepage/cdpsl852.c
  * harbour/source/codepage/cdpsliso.c
  * harbour/source/codepage/cdpslwin.c
  * harbour/source/codepage/cdpsrwin.c
  * harbour/source/rtl/cdpapi.c
    * fix memory leak reported for accented and multi byte CPs

  + harbour/source/codepage/cdpesmwi.c
    * added missing Spanish modern CP

  * harbour/include/hbstack.h
  * harbour/include/hbapiitm.h
  * harbour/source/vm/estack.c
  * harbour/source/vm/itemapi.c
    + added hb_stackReturnItem()
    - removed hb_itemReturnPtr()

  * harbour/source/rdd/workarea.c
    ! fixed possible restoring of scopes in scoped relations after
      'SET RELATION TO'

  * harbour/source/rdd/dbfcdx/dbfcdx1.c
  * harbour/source/rdd/dbfdbt/dbfdbt1.c
  * harbour/source/rdd/dbffpt/dbffpt1.c
    * use hb_stackReturnItem() instead of direct stack accessing

  * harbour/source/rdd/dbfntx/dbfntx1.c
    ! Fixed opening NTX file in ReadOnly mode
    * use hb_stackReturnItem() instead of direct stack accessing

  * harbour/source/rtl/filesys.c
    * cleaned unnecessary initialization

  * harbour/source/vm/memvars.c
    * formatting and small fix for calling GC after hb_memvarsRelease()
2004-12-31 11:47:58 +00:00

2244 lines
52 KiB
C

/*
* $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 <viktor.szakats@syenar.hu>
* hb_fsSetError()
* hb_fsSetDevMode()
* hb_fsReadLarge()
* hb_fsWriteLarge()
* hb_fsCurDirBuff()
*
* Copyright 1999 Jose Lalin <dezac@corevia.com>
* hb_fsChDrv()
* hb_fsCurDrv()
* hb_fsIsDrv()
* hb_fsIsDevice()
*
* Copyright 2000 Luiz Rafael Culik <culik@sl.conex.net>
* and David G. Holm <dholm@jsd-llc.com>
* hb_fsEof()
*
* Copyright 2001 Jose Gimenez (JFG) <jfgimenez@wanadoo.es>
* <tecnico.sireinsa@ctv.es>
* 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 <string.h>
#include <ctype.h>
#include "hbapi.h"
#include "hbapifs.h"
#include "hbset.h"
#include "hb_io.h"
#if defined(OS_UNIX_COMPATIBLE)
#include <unistd.h>
#endif
#if defined(__GNUC__) && !defined(__MINGW32__)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#if defined(__CYGWIN__)
#include <io.h>
#endif
#if defined(__DJGPP__)
#include <dir.h>
#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 <sys/stat.h>
#include <share.h>
#include <fcntl.h>
#include <direct.h>
#include <errno.h>
#include <dos.h>
#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 <sys\stat.h>
#include <share.h>
#include <fcntl.h>
#include <direct.h>
#if defined(__BORLANDC__)
#include <dir.h>
#include <dos.h>
#include <windows.h>
#endif
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <sys\locking.h>
#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 <errno.h>
#endif
#if defined(__MPW__)
#include <fcntl.h>
#endif
#if defined(HB_OS_DOS)
#include <dos.h>
#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 <directory search> */
#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 <directory search> */
#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<strlen(str);a++)
if( str[a] == '\\' )
str[a] = hb_set.HB_SET_DIRSEPARATOR;
}
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);
}