From c89f63ee0bb9caf175bcb2ca81dfcd97a5a07cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Czerpak?= Date: Thu, 6 Mar 2014 19:07:49 +0100 Subject: [PATCH] 2014-03-06 19:07 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * src/vm/set.c ! fixed freed memory access exploited by interactions between modifications in last few years. ! do not try to remove trailing ^Z char reading from the stream if FS_END seek reports 0. ! if possible open printer/alternate/extra output in write only mode to avoid problem on devices where read access is not available. * src/rtl/langapi.c * keep EN lang active after deinitialization * src/rtl/filesys.c ! fixed condition for file time refresh in *nix builds ! fixed file time setting in *nix builds * include/hbapifs.h * src/rtl/Makefile * src/rtl/filebuf.c + src/rtl/filebufd.c * renamed hb_fileRegister2() to hb_fileRegisterFull() + added new function hb_fileRegisterPart() which simplifies writing small FILE IO redirectors. * contrib/hbmemio/memio.c * contrib/hbnetio/netiocli.c * use hb_fileRegisterFull() * contrib/hbplist.txt + contrib/hbtcpio/hbtcpio.hbc + contrib/hbtcpio/hbtcpio.hbp + contrib/hbtcpio/hbtcpio.hbx + contrib/hbtcpio/tcpio.c + added new Harbour FILE IO redirector. It recognizes and process names with "tcp:" prefix, in form like: tcp::[:] It can be used in different subsystems using Harbour FILE IO and stream read/write operations, i.e. REQUEST HB_TCPIO SET PRINTER TO tcp:192.168.0.110:9100 can be used to connect to network printers using TCP direct printing. * utils/hbmk2/po/hbmk2.pt_BR.po ! fixed typo in translation --- ChangeLog.txt | 45 ++++ contrib/hbmemio/memio.c | 2 +- contrib/hbnetio/netiocli.c | 2 +- contrib/hbplist.txt | 1 + contrib/hbtcpio/hbtcpio.hbc | 3 + contrib/hbtcpio/hbtcpio.hbp | 10 + contrib/hbtcpio/hbtcpio.hbx | 30 +++ contrib/hbtcpio/tcpio.c | 314 +++++++++++++++++++++++ include/hbapifs.h | 3 +- src/rtl/Makefile | 1 + src/rtl/filebuf.c | 2 +- src/rtl/filebufd.c | 458 ++++++++++++++++++++++++++++++++++ src/rtl/filesys.c | 11 +- src/rtl/langapi.c | 5 +- src/vm/set.c | 100 ++++---- utils/hbmk2/po/hbmk2.pt_BR.po | 2 +- 16 files changed, 926 insertions(+), 63 deletions(-) create mode 100644 contrib/hbtcpio/hbtcpio.hbc create mode 100644 contrib/hbtcpio/hbtcpio.hbp create mode 100644 contrib/hbtcpio/hbtcpio.hbx create mode 100644 contrib/hbtcpio/tcpio.c create mode 100644 src/rtl/filebufd.c diff --git a/ChangeLog.txt b/ChangeLog.txt index 2e87b27b6c..5114db0d4c 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,51 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2014-03-06 19:07 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * src/vm/set.c + ! fixed freed memory access exploited by interactions between + modifications in last few years. + ! do not try to remove trailing ^Z char reading from the stream + if FS_END seek reports 0. + ! if possible open printer/alternate/extra output in write only mode + to avoid problem on devices where read access is not available. + + * src/rtl/langapi.c + * keep EN lang active after deinitialization + + * src/rtl/filesys.c + ! fixed condition for file time refresh in *nix builds + ! fixed file time setting in *nix builds + + * include/hbapifs.h + * src/rtl/Makefile + * src/rtl/filebuf.c + + src/rtl/filebufd.c + * renamed hb_fileRegister2() to hb_fileRegisterFull() + + added new function hb_fileRegisterPart() which simplifies writing + small FILE IO redirectors. + + * contrib/hbmemio/memio.c + * contrib/hbnetio/netiocli.c + * use hb_fileRegisterFull() + + * contrib/hbplist.txt + + contrib/hbtcpio/hbtcpio.hbc + + contrib/hbtcpio/hbtcpio.hbp + + contrib/hbtcpio/hbtcpio.hbx + + contrib/hbtcpio/tcpio.c + + added new Harbour FILE IO redirector. + It recognizes and process names with "tcp:" prefix, in form like: + tcp::[:] + It can be used in different subsystems using Harbour FILE IO and + stream read/write operations, i.e. + REQUEST HB_TCPIO + SET PRINTER TO tcp:192.168.0.110:9100 + can be used to connect to network printers using TCP direct printing. + + * utils/hbmk2/po/hbmk2.pt_BR.po + ! fixed typo in translation + 2014-03-05 11:59 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * src/debug/dbgentry.c ! added additional protection against recursive debugger activation. diff --git a/contrib/hbmemio/memio.c b/contrib/hbmemio/memio.c index 7e5d6c3b0d..50e87a9485 100644 --- a/contrib/hbmemio/memio.c +++ b/contrib/hbmemio/memio.c @@ -1123,7 +1123,7 @@ HB_FUNC( HB_MEMIO ) { ; } HB_CALL_ON_STARTUP_BEGIN( _hb_file_memio_init_ ) memfsInit(); - hb_fileRegister2( &s_fileFuncs ); + hb_fileRegisterFull( &s_fileFuncs ); HB_CALL_ON_STARTUP_END( _hb_file_memio_init_ ) #if defined( HB_PRAGMA_STARTUP ) diff --git a/contrib/hbnetio/netiocli.c b/contrib/hbnetio/netiocli.c index bc8c222770..e1b7545c02 100644 --- a/contrib/hbnetio/netiocli.c +++ b/contrib/hbnetio/netiocli.c @@ -972,7 +972,7 @@ static void s_netio_init( void * cargo ) if( s_fInit ) { hb_socketInit(); - hb_fileRegister2( s_fileMethods() ); + hb_fileRegisterFull( s_fileMethods() ); hb_vmAtQuit( s_netio_exit, NULL ); s_fInit = HB_FALSE; } diff --git a/contrib/hbplist.txt b/contrib/hbplist.txt index af14d06cf9..2fc02e5371 100644 --- a/contrib/hbplist.txt +++ b/contrib/hbplist.txt @@ -40,6 +40,7 @@ hbrun/hbrun.hbp hbsms/hbsms.hbp hbsqlit3/hbsqlit3.hbp # uses: sqlite3 (locally hosted) hbssl/hbssl.hbp +hbtcpio/hbtcpio.hbp hbtip/hbtip.hbp hbtinymt/hbtinymt.hbp hbtpathy/hbtpathy.hbp diff --git a/contrib/hbtcpio/hbtcpio.hbc b/contrib/hbtcpio/hbtcpio.hbc new file mode 100644 index 0000000000..7091cfe233 --- /dev/null +++ b/contrib/hbtcpio/hbtcpio.hbc @@ -0,0 +1,3 @@ +description=I/O driver for TCP streams + +libs=${_HB_DYNPREF}${hb_name}${_HB_DYNSUFF} diff --git a/contrib/hbtcpio/hbtcpio.hbp b/contrib/hbtcpio/hbtcpio.hbp new file mode 100644 index 0000000000..8a680b2cc8 --- /dev/null +++ b/contrib/hbtcpio/hbtcpio.hbp @@ -0,0 +1,10 @@ +-hblib +-inc + +-o${hb_name} + +-w3 -es2 + +${hb_name}.hbx + +tcpio.c diff --git a/contrib/hbtcpio/hbtcpio.hbx b/contrib/hbtcpio/hbtcpio.hbx new file mode 100644 index 0000000000..11166efbfd --- /dev/null +++ b/contrib/hbtcpio/hbtcpio.hbx @@ -0,0 +1,30 @@ +/* -------------------------------------------------------------------- + * NOTE: You can add manual override which functions to include or + * exclude from automatically generated EXTERNAL/DYNAMIC list. + * Syntax: // HB_FUNC_INCLUDE + * // HB_FUNC_EXCLUDE + */ + +/* -------------------------------------------------------------------- + * WARNING: Automatically generated code below. DO NOT EDIT! (except casing) + * Regenerate using hbmk2 '-hbx=' option. + */ + +#ifndef __HBEXTERN_CH__HBTCPIO__ +#define __HBEXTERN_CH__HBTCPIO__ + +#if defined( __HBEXTREQ__ ) .OR. defined( __HBEXTERN__HBTCPIO__ANNOUNCE ) + ANNOUNCE __HBEXTERN__HBTCPIO__ +#endif + +#if defined( __HBEXTREQ__ ) .OR. defined( __HBEXTERN__HBTCPIO__REQUEST ) + #command DYNAMIC => EXTERNAL +#endif + +DYNAMIC HB_TCPIO + +#if defined( __HBEXTREQ__ ) .OR. defined( __HBEXTERN__HBTCPIO__REQUEST ) + #uncommand DYNAMIC => EXTERNAL +#endif + +#endif diff --git a/contrib/hbtcpio/tcpio.c b/contrib/hbtcpio/tcpio.c new file mode 100644 index 0000000000..7f300af3c1 --- /dev/null +++ b/contrib/hbtcpio/tcpio.c @@ -0,0 +1,314 @@ +/* + * Harbour Project source code: + * I/O driver for TCP streams + * + * Copyright 2014 Przemyslaw Czerpak + * www - http://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.txt. 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. + * + */ + +/* this has to be declared before hbapifs.h is included */ +#define _HB_FILE_IMPLEMENTATION_ + +#include "hbapi.h" +#include "hbapifs.h" +#include "hbapierr.h" +#include "hbinit.h" + +#include "hbsocket.h" + +#define FILE_PREFIX "tcp:" +#define FILE_PREFIX_LEN strlen( FILE_PREFIX ) + +typedef struct _HB_FILE +{ + const HB_FILE_FUNCS * pFuncs; + HB_SOCKET sd; + HB_BOOL fEof; + int timeout; +} +HB_FILE; + +static PHB_FILE s_fileNew( HB_FHANDLE hFile, int timeout ); + +static HB_BOOL s_fileAccept( const char * pszFileName ) +{ + return hb_strnicmp( pszFileName, FILE_PREFIX, FILE_PREFIX_LEN ) == 0; +} + +static PHB_FILE s_fileOpen( const char * pszName, const char * pszDefExt, + HB_USHORT uiExFlags, + const char * pPaths, PHB_ITEM pError ) +{ + const char * pszHost = pszName + FILE_PREFIX_LEN, * ptr; + PHB_FILE pFile = NULL; + HB_ERRCODE errcode = 0; + HB_SIZE nLen = 0; + int iPort = 0; + int timeout = -1; + + HB_SYMBOL_UNUSED( pszDefExt ); + HB_SYMBOL_UNUSED( pPaths ); + + if( ( ptr = strchr( pszHost, ':' ) ) != NULL && ptr != pszHost ) + { + nLen = ptr - pszHost; + ++ptr; + while( HB_ISDIGIT( * ptr ) ) + iPort = iPort * 10 + ( * ptr++ - '0' ); + + if( * ptr == ':' ) + { + ++ptr; + while( HB_ISDIGIT( * ptr ) ) + timeout = HB_MAX( timeout, 0 ) * 10 + ( * ptr++ - '0' ); + } + + if( * ptr != 0 && * ptr != ':' ) + iPort = 0; + } + + if( iPort > 0 ) + { + char * pszAddr, * pszIpAddr; + + pszAddr = hb_strndup( pszHost, nLen ); + pszIpAddr = hb_socketResolveAddr( pszAddr, HB_SOCKET_AF_INET ); + hb_xfree( pszAddr ); + + if( pszIpAddr ) + { + HB_SOCKET sd = hb_socketOpen( HB_SOCKET_PF_INET, HB_SOCKET_PT_STREAM, 0 ); + if( sd != HB_NO_SOCKET ) + { + void * pSockAddr; + unsigned uiLen; + + if( hb_socketInetAddr( &pSockAddr, &uiLen, pszIpAddr, iPort ) ) + { + hb_socketSetKeepAlive( sd, HB_TRUE ); + if( hb_socketConnect( sd, pSockAddr, uiLen, timeout ) == 0 ) + { + switch( uiExFlags & 0x3 ) + { + case FO_READ: + hb_socketShutdown( sd, HB_SOCKET_SHUT_WR ); + break; + case FO_WRITE: + hb_socketShutdown( sd, HB_SOCKET_SHUT_RD ); + break; + } + pFile = s_fileNew( sd, timeout ); + sd = HB_NO_SOCKET; + } + hb_xfree( pSockAddr ); + } + if( sd != HB_NO_SOCKET ) + { + errcode = hb_socketGetError(); + hb_socketClose( sd ); + } + } + hb_xfree( pszIpAddr ); + } + if( errcode == 0 && pFile == NULL ) + errcode = hb_socketGetError(); + } + else + errcode = HB_SOCKET_ERR_WRONGADDR; + + hb_fsSetError( errcode ); + + if( pError ) + { + hb_errPutFileName( pError, pszName ); + if( pFile == NULL ) + { + hb_errPutOsCode( pError, errcode ); + hb_errPutGenCode( pError, ( HB_ERRCODE ) EG_OPEN ); + } + } + + return pFile; +} + +static void s_fileClose( PHB_FILE pFile ) +{ + hb_socketClose( pFile->sd ); + hb_fsSetError( hb_socketGetError() ); + hb_xfree( pFile ); +} + +static HB_SIZE s_fileRead( PHB_FILE pFile, void * data, + HB_SIZE nSize, HB_MAXINT timeout ) +{ + HB_ERRCODE errcode = 0; + long lRead = 0; + + if( ! pFile->fEof ) + { + lRead = nSize > LONG_MAX ? LONG_MAX : ( long ) nSize; + lRead = hb_socketRecv( pFile->sd, data, lRead, 0, timeout ); + + errcode = hb_socketGetError(); + + if( lRead <= 0 ) + { + switch( errcode ) + { + case HB_SOCKET_ERR_TIMEOUT: + case HB_SOCKET_ERR_AGAIN: + case HB_SOCKET_ERR_TRYAGAIN: + break; + default: + pFile->fEof = HB_TRUE; + break; + } + lRead = 0; + } + } + hb_fsSetError( errcode ); + + return lRead; +} + +static HB_SIZE s_fileWrite( PHB_FILE pFile, const void * data, + HB_SIZE nSize, HB_MAXINT timeout ) +{ + long lSend = nSize > LONG_MAX ? LONG_MAX : ( long ) nSize; + + lSend = hb_socketSend( pFile->sd, data, lSend, 0, timeout ); + hb_fsSetError( hb_socketGetError() ); + + if( lSend < 0 ) + lSend = 0; + + return lSend; +} + +static HB_BOOL s_fileEof( PHB_FILE pFile ) +{ + hb_fsSetError( 0 ); + return pFile->fEof; +} + +static HB_BOOL s_fileConfigure( PHB_FILE pFile, int iIndex, PHB_ITEM pValue ) +{ + HB_SYMBOL_UNUSED( pFile ); + HB_SYMBOL_UNUSED( iIndex ); + HB_SYMBOL_UNUSED( pValue ); + + return HB_FALSE; +} + +static HB_FHANDLE s_fileHandle( PHB_FILE pFile ) +{ + return ( HB_FHANDLE ) ( pFile ? pFile->sd : HB_NO_SOCKET ); +} + +static HB_FILE_FUNCS s_fileFuncs = +{ + s_fileAccept, + + NULL, /* s_fileExists */ + NULL, /* s_fileDelete */ + NULL, /* s_fileRename */ + NULL, /* s_fileCopy */ + + NULL, /* s_fileDirExists */ + NULL, /* s_fileDirMake */ + NULL, /* s_fileDirRemove */ + NULL, /* s_fileDirSpace */ + NULL, /* s_fileDirectory */ + + NULL, /* s_fileTimeGet */ + NULL, /* s_fileTimeSet */ + NULL, /* s_fileAttrGet */ + NULL, /* s_fileAttrSet */ + + NULL, /* s_fileLink */ + NULL, /* s_fileLinkSym */ + NULL, /* s_fileLinkRead */ + + s_fileOpen, + s_fileClose, + NULL, /* s_fileLock */ + NULL, /* s_fileLockTest */ + s_fileRead, + s_fileWrite, + NULL, /* s_fileReadAt */ + NULL, /* s_fileWriteAt */ + NULL, /* s_fileTruncAt */ + NULL, /* s_fileSeek */ + NULL, /* s_fileSize */ + s_fileEof, + NULL, /* s_fileFlush */ + NULL, /* s_fileCommit */ + s_fileConfigure, + s_fileHandle +}; + +static PHB_FILE s_fileNew( HB_SOCKET sd, int timeout ) +{ + PHB_FILE pFile = ( PHB_FILE ) hb_xgrab( sizeof( HB_FILE ) ); + + pFile->pFuncs = &s_fileFuncs; + pFile->sd = sd; + pFile->fEof = HB_FALSE; + pFile->timeout = timeout; + + return pFile; +} + +HB_FUNC( HB_TCPIO ) { ; } + + +HB_CALL_ON_STARTUP_BEGIN( _hb_file_tcpio_init_ ) + hb_fileRegisterPart( &s_fileFuncs ); +HB_CALL_ON_STARTUP_END( _hb_file_tcpio_init_ ) + +#if defined( HB_PRAGMA_STARTUP ) + #pragma startup _hb_file_tcpio_init_ +#elif defined( HB_DATASEG_STARTUP ) + #define HB_DATASEG_BODY HB_DATASEG_FUNC( _hb_file_tcpio_init_ ) + #include "hbiniseg.h" +#endif diff --git a/include/hbapifs.h b/include/hbapifs.h index 15c201d4d8..c53a520a33 100644 --- a/include/hbapifs.h +++ b/include/hbapifs.h @@ -352,7 +352,8 @@ extern HB_EXPORT HB_WCHAR * hb_fsNameConvU16( const char * pszFileName ); } HB_FILE_FUNCS; - extern HB_EXPORT HB_BOOL hb_fileRegister2( const HB_FILE_FUNCS * pFuncs ); + extern HB_EXPORT HB_BOOL hb_fileRegisterFull( const HB_FILE_FUNCS * pFuncs ); + extern HB_EXPORT HB_BOOL hb_fileRegisterPart( HB_FILE_FUNCS * pFuncs ); #else typedef void * PHB_FILE; #endif diff --git a/src/rtl/Makefile b/src/rtl/Makefile index ac4a9f4fac..7b866a095a 100644 --- a/src/rtl/Makefile +++ b/src/rtl/Makefile @@ -48,6 +48,7 @@ C_SOURCES := \ errintlo.c \ file.c \ filebuf.c \ + filebufd.c \ filehb.c \ filesys.c \ fkmax.c \ diff --git a/src/rtl/filebuf.c b/src/rtl/filebuf.c index 0eb139b8f8..2d924206bc 100644 --- a/src/rtl/filebuf.c +++ b/src/rtl/filebuf.c @@ -921,7 +921,7 @@ static int s_fileFindDrv( const char * pszFileName ) * public API functions */ -HB_BOOL hb_fileRegister2( const HB_FILE_FUNCS * pFuncs ) +HB_BOOL hb_fileRegisterFull( const HB_FILE_FUNCS * pFuncs ) { HB_BOOL fResult = HB_FALSE; diff --git a/src/rtl/filebufd.c b/src/rtl/filebufd.c new file mode 100644 index 0000000000..2443a4f497 --- /dev/null +++ b/src/rtl/filebufd.c @@ -0,0 +1,458 @@ +/* + * Harbour Project source code: + * dummy I/O driver initialization + * + * Copyright 2014 Przemyslaw Czerpak + * www - http://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.txt. 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. + * + */ + +/* this has to be declared before hbapifs.h is included */ +#define _HB_FILE_IMPLEMENTATION_ + +#include "hbapi.h" +#include "hbapifs.h" + +#define HB_FILE_ERR_UNSUPPORTED ( ( HB_ERRCODE ) FS_ERROR ) + +static HB_BOOL s_fileAccept( const char * pszFileName ) +{ + HB_SYMBOL_UNUSED( pszFileName ); + + return HB_FALSE; +} + +static HB_BOOL s_fileExists( const char * pszFileName, char * pRetPath ) +{ + HB_SYMBOL_UNUSED( pszFileName ); + HB_SYMBOL_UNUSED( pRetPath ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static HB_BOOL s_fileDelete( const char * pszFileName ) +{ + HB_SYMBOL_UNUSED( pszFileName ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static HB_BOOL s_fileRename( const char * pszName, const char * pszNewName ) +{ + HB_SYMBOL_UNUSED( pszName ); + HB_SYMBOL_UNUSED( pszNewName ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static HB_BOOL s_fileCopy( const char * pSrcFile, const char * pszDstFile ) +{ + HB_SYMBOL_UNUSED( pSrcFile ); + HB_SYMBOL_UNUSED( pszDstFile ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static HB_BOOL s_fileDirExists( const char * pszDirName ) +{ + HB_SYMBOL_UNUSED( pszDirName ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static HB_BOOL s_fileDirMake( const char * pszDirName ) +{ + HB_SYMBOL_UNUSED( pszDirName ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static HB_BOOL s_fileDirRemove( const char * pszDirName ) +{ + HB_SYMBOL_UNUSED( pszDirName ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static double s_fileDirSpace( const char * pszDirName, HB_USHORT uiType ) +{ + HB_SYMBOL_UNUSED( pszDirName ); + HB_SYMBOL_UNUSED( uiType ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return 0.0; +} + +static PHB_ITEM s_fileDirectory( const char * pszDirSpec, const char * pszAttr ) +{ + HB_SYMBOL_UNUSED( pszDirSpec ); + HB_SYMBOL_UNUSED( pszAttr ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return NULL; +} + +static HB_BOOL s_fileTimeGet( const char * pszFileName, long * plJulian, long * plMillisec ) +{ + HB_SYMBOL_UNUSED( pszFileName ); + HB_SYMBOL_UNUSED( plJulian ); + HB_SYMBOL_UNUSED( plMillisec ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static HB_BOOL s_fileTimeSet( const char * pszFileName, long lJulian, long lMillisec ) +{ + HB_SYMBOL_UNUSED( pszFileName ); + HB_SYMBOL_UNUSED( lJulian ); + HB_SYMBOL_UNUSED( lMillisec ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static HB_BOOL s_fileAttrGet( const char * pszFileName, HB_FATTR * pnAttr ) +{ + HB_SYMBOL_UNUSED( pszFileName ); + HB_SYMBOL_UNUSED( pnAttr ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static HB_BOOL s_fileAttrSet( const char * pszFileName, HB_FATTR nAttr ) +{ + HB_SYMBOL_UNUSED( pszFileName ); + HB_SYMBOL_UNUSED( nAttr ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static HB_BOOL s_fileLink( const char * pszExisting, const char * pszNewName ) +{ + HB_SYMBOL_UNUSED( pszExisting ); + HB_SYMBOL_UNUSED( pszNewName ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static HB_BOOL s_fileLinkSym( const char * pszTarget, const char * pszNewName ) +{ + HB_SYMBOL_UNUSED( pszTarget ); + HB_SYMBOL_UNUSED( pszNewName ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static char * s_fileLinkRead( const char * pszFileName ) +{ + HB_SYMBOL_UNUSED( pszFileName ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return NULL; +} + +static PHB_FILE s_fileOpen( const char * pszName, const char * pszDefExt, HB_USHORT uiExFlags, + const char * pPaths, PHB_ITEM pError ) +{ + HB_SYMBOL_UNUSED( pszName ); + HB_SYMBOL_UNUSED( pszDefExt ); + HB_SYMBOL_UNUSED( uiExFlags ); + HB_SYMBOL_UNUSED( pszDefExt ); + HB_SYMBOL_UNUSED( pPaths ); + HB_SYMBOL_UNUSED( pError ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return NULL; +} + +static void s_fileClose( PHB_FILE pFile ) +{ + HB_SYMBOL_UNUSED( pFile ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); +} + +static HB_BOOL s_fileLock( PHB_FILE pFile, HB_FOFFSET nStart, + HB_FOFFSET nLen, int iType ) +{ + HB_SYMBOL_UNUSED( pFile ); + HB_SYMBOL_UNUSED( nStart ); + HB_SYMBOL_UNUSED( nLen ); + HB_SYMBOL_UNUSED( iType ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static int s_fileLockTest( PHB_FILE pFile, HB_FOFFSET nStart, + HB_FOFFSET nLen, int iType ) +{ + HB_SYMBOL_UNUSED( pFile ); + HB_SYMBOL_UNUSED( nStart ); + HB_SYMBOL_UNUSED( nLen ); + HB_SYMBOL_UNUSED( iType ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return -1; +} + +static HB_SIZE s_fileRead( PHB_FILE pFile, void * data, + HB_SIZE nSize, HB_MAXINT timeout ) +{ + HB_SYMBOL_UNUSED( pFile ); + HB_SYMBOL_UNUSED( data ); + HB_SYMBOL_UNUSED( nSize ); + HB_SYMBOL_UNUSED( timeout ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return 0; +} + +static HB_SIZE s_fileWrite( PHB_FILE pFile, const void * data, + HB_SIZE nSize, HB_MAXINT timeout ) +{ + HB_SYMBOL_UNUSED( pFile ); + HB_SYMBOL_UNUSED( data ); + HB_SYMBOL_UNUSED( nSize ); + HB_SYMBOL_UNUSED( timeout ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return 0; +} + +static HB_SIZE s_fileReadAt( PHB_FILE pFile, void * buffer, + HB_SIZE nSize, HB_FOFFSET nOffset ) +{ + HB_SYMBOL_UNUSED( pFile ); + HB_SYMBOL_UNUSED( buffer ); + HB_SYMBOL_UNUSED( nSize ); + HB_SYMBOL_UNUSED( nOffset ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return 0; +} + +static HB_SIZE s_fileWriteAt( PHB_FILE pFile, const void * buffer, + HB_SIZE nSize, HB_FOFFSET nOffset ) +{ + HB_SYMBOL_UNUSED( pFile ); + HB_SYMBOL_UNUSED( buffer ); + HB_SYMBOL_UNUSED( nSize ); + HB_SYMBOL_UNUSED( nOffset ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return 0; +} + +static HB_BOOL s_fileTruncAt( PHB_FILE pFile, HB_FOFFSET nOffset ) +{ + HB_SYMBOL_UNUSED( pFile ); + HB_SYMBOL_UNUSED( nOffset ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static HB_FOFFSET s_fileSeek( PHB_FILE pFile, HB_FOFFSET nOffset, + HB_USHORT uiFlags ) +{ + HB_SYMBOL_UNUSED( pFile ); + HB_SYMBOL_UNUSED( nOffset ); + HB_SYMBOL_UNUSED( uiFlags ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return 0; +} + +static HB_FOFFSET s_fileSize( PHB_FILE pFile ) +{ + HB_SYMBOL_UNUSED( pFile ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return 0; +} + +static HB_BOOL s_fileEof( PHB_FILE pFile ) +{ + HB_SYMBOL_UNUSED( pFile ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_TRUE; +} + +static void s_fileFlush( PHB_FILE pFile, HB_BOOL fDirty ) +{ + HB_SYMBOL_UNUSED( pFile ); + HB_SYMBOL_UNUSED( fDirty ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); +} + +static void s_fileCommit( PHB_FILE pFile ) +{ + HB_SYMBOL_UNUSED( pFile ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); +} + +static HB_BOOL s_fileConfigure( PHB_FILE pFile, int iIndex, PHB_ITEM pValue ) +{ + HB_SYMBOL_UNUSED( pFile ); + HB_SYMBOL_UNUSED( iIndex ); + HB_SYMBOL_UNUSED( pValue ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return HB_FALSE; +} + +static HB_FHANDLE s_fileHandle( PHB_FILE pFile ) +{ + HB_SYMBOL_UNUSED( pFile ); + + hb_fsSetError( HB_FILE_ERR_UNSUPPORTED ); + + return ( HB_FHANDLE ) FS_ERROR; +} + +static const HB_FILE_FUNCS s_fileFuncs = +{ + s_fileAccept, + + s_fileExists, + s_fileDelete, + s_fileRename, + s_fileCopy, + + s_fileDirExists, + s_fileDirMake, + s_fileDirRemove, + s_fileDirSpace, + s_fileDirectory, + + s_fileTimeGet, + s_fileTimeSet, + s_fileAttrGet, + s_fileAttrSet, + + s_fileLink, + s_fileLinkSym, + s_fileLinkRead, + + s_fileOpen, + s_fileClose, + s_fileLock, + s_fileLockTest, + s_fileRead, + s_fileWrite, + s_fileReadAt, + s_fileWriteAt, + s_fileTruncAt, + s_fileSeek, + s_fileSize, + s_fileEof, + s_fileFlush, + s_fileCommit, + s_fileConfigure, + s_fileHandle +}; + +typedef void * ( * HB_FILE_FUNC )( PHB_FILE ); +#define HB_FILE_FUNC_COUNT ( sizeof( HB_FILE_FUNCS ) / sizeof( HB_FILE_FUNC ) ) + +HB_BOOL hb_fileRegisterPart( HB_FILE_FUNCS * pFuncs ) +{ + const HB_FILE_FUNC * pDummyFunc; + HB_FILE_FUNC * pFunction; + int iCount; + + pDummyFunc = ( const HB_FILE_FUNC * ) &s_fileFuncs; + pFunction = ( HB_FILE_FUNC * ) pFuncs; + + for( iCount = 0; iCount < ( int ) HB_FILE_FUNC_COUNT; + iCount++, pDummyFunc++, pFunction++ ) + { + if( * pFunction == NULL ) + * pFunction = * pDummyFunc; + } + + return hb_fileRegisterFull( pFuncs ); +} diff --git a/src/rtl/filesys.c b/src/rtl/filesys.c index 7896dc0d74..a30e2d573d 100644 --- a/src/rtl/filesys.c +++ b/src/rtl/filesys.c @@ -1602,7 +1602,7 @@ HB_BOOL hb_fsSetFileTime( const char * pszFileName, long lJulian, long lMillisec pszFileName = hb_fsNameConv( pszFileName, &pszFree ); - if( lJulian <= 0 && lMillisec ) + if( lJulian <= 0 && lMillisec < 0 ) { # if defined( HB_OS_LINUX ) && ! defined( __WATCOMC__ ) fResult = utimes( pszFileName, NULL ) == 0; @@ -1613,7 +1613,6 @@ HB_BOOL hb_fsSetFileTime( const char * pszFileName, long lJulian, long lMillisec else { struct tm new_value; - time_t tim; if( lJulian <= 0 || lMillisec < 0 ) { @@ -1641,12 +1640,8 @@ HB_BOOL hb_fsSetFileTime( const char * pszFileName, long lJulian, long lMillisec new_value.tm_min = iMinute; new_value.tm_sec = iSecond; } - tim = mktime( &new_value ); -# if defined( HB_HAS_LOCALTIME_R ) - gmtime_r( &tim, &new_value ); -# else - new_value = *gmtime( &tim ); -# endif + new_value.tm_isdst = 0; + # if defined( HB_OS_LINUX ) && ! defined( __WATCOMC__ ) { struct timeval times[ 2 ]; diff --git a/src/rtl/langapi.c b/src/rtl/langapi.c index 00f51667b4..352a1e4c7e 100644 --- a/src/rtl/langapi.c +++ b/src/rtl/langapi.c @@ -229,8 +229,11 @@ static void hb_langRelease( PHB_LANG_BASE pBase ) if( pBase->lang ) { if( pBase->buffer ) + { hb_xfree( pBase->buffer ); - pBase->lang = NULL; + pBase->buffer = NULL; + } + pBase->lang = pBase == s_langList ? &s_lang_en : NULL; } } diff --git a/src/vm/set.c b/src/vm/set.c index c6381030e9..cc6c2b7e88 100644 --- a/src/vm/set.c +++ b/src/vm/set.c @@ -242,19 +242,18 @@ static const char * is_devicename( const char * szFileName ) } static void open_handle( PHB_SET_STRUCT pSet, const char * file_name, - HB_BOOL bAppend, HB_set_enum set_specifier ) + HB_BOOL fAppend, HB_set_enum set_specifier ) { HB_STACK_TLS_PRELOAD PHB_ITEM pError = NULL; PHB_FILE handle, * handle_ptr; HB_ERRCODE uiError; - const char * szDevice = NULL; - const char * szFileName = NULL; - const char * def_ext; + const char * szDevice = NULL, * def_ext; + char * szFileName = NULL; char ** set_value; - HB_BOOL bPipe = HB_FALSE; + HB_BOOL fPipe = HB_FALSE, fStripEof; - HB_TRACE( HB_TR_DEBUG, ( "open_handle(%p, %s, %d, %d)", pSet, file_name, ( int ) bAppend, ( int ) set_specifier ) ); + HB_TRACE( HB_TR_DEBUG, ( "open_handle(%p, %s, %d, %d)", pSet, file_name, ( int ) fAppend, ( int ) set_specifier ) ); switch( set_specifier ) { @@ -280,85 +279,59 @@ static void open_handle( PHB_SET_STRUCT pSet, const char * file_name, return; } - close_handle( pSet, set_specifier ); - if( file_name && file_name[ 0 ] != '\0' ) { #if defined( HB_OS_UNIX ) - bPipe = file_name[ 0 ] == '|'; - if( bPipe ) - { - szFileName = file_name; - bAppend = HB_FALSE; - } + fPipe = file_name[ 0 ] == '|'; + if( fPipe ) + szFileName = hb_strdup( file_name ); else #endif { szDevice = is_devicename( file_name ); if( szDevice ) { - szFileName = szDevice; + szFileName = hb_strdup( szDevice ); def_ext = NULL; } else - szFileName = file_name; + szFileName = hb_strdup( file_name ); } } /* free the old value before setting the new one (CA-Cl*pper does it). * This code must be executed after setting szFileName, [druzus] */ + close_handle( pSet, set_specifier ); if( *set_value ) + { hb_xfree( *set_value ); - *set_value = NULL; + *set_value = NULL; + } if( ! szFileName ) return; - /* Open the file either in append (bAppend) or truncate mode (! bAppend), but + fStripEof = fAppend && szDevice == NULL && ! fPipe; + + /* Open the file either in append (fAppend) or truncate mode (! fAppend), but always use binary mode */ /* QUESTION: What sharing mode does Clipper use ? [vszakats] */ do { - if( bPipe ) - { + if( fPipe ) handle = hb_filePOpen( szFileName + 1, "w" ); - } else - { handle = hb_fileExtOpen( szFileName, hb_stackSetStruct()->HB_SET_DEFEXTENSIONS ? def_ext : NULL, - FO_READWRITE | FO_READWRITE | FXO_SHARELOCK | - ( bAppend ? FXO_APPEND : FXO_TRUNCATE ) | + ( !fStripEof || set_specifier == HB_SET_PRINTFILE ? FO_WRITE : FO_READWRITE ) | + FO_DENYWRITE | FXO_SHARELOCK | + ( fAppend ? FXO_APPEND : FXO_TRUNCATE ) | ( szDevice ? 0 : FXO_DEFAULTS ), NULL, pError ); - if( handle != NULL && szDevice == NULL && bAppend ) - { - /* Position to EOF */ - /* Special binary vs. text file handling - even for UN*X, now - that there's an HB_SET_EOF flag. */ - if( set_specifier == HB_SET_PRINTFILE ) - { - /* PRINTFILE is always binary and needs no special handling. */ - hb_fileSeek( handle, 0, FS_END ); - } - else - { - /* All other files are text files and may have an EOF - ('\x1A') character at the end (both UN*X and non-UN*X, - now that theres an HB_SET_EOF flag). */ - char cEOF = '\0'; - hb_fileSeek( handle, -1, FS_END ); /* Position to last char. */ - hb_fileRead( handle, &cEOF, 1, -1 ); /* Read the last char. */ - if( cEOF == '\x1A' ) /* If it's an EOF, */ - hb_fileSeek( handle, -1, FS_END ); /* Then write over it. */ - } - } - } - if( handle == NULL ) { pError = hb_errRT_FileError( pError, HB_ERR_SS_TERMINAL, EG_CREATE, uiError, szFileName ); @@ -371,14 +344,43 @@ static void open_handle( PHB_SET_STRUCT pSet, const char * file_name, if( pError ) hb_itemRelease( pError ); + if( handle != NULL && fStripEof ) + { + /* Position to EOF */ + if( hb_fileSeek( handle, 0, FS_END ) > 0 ) + { + /* Special binary vs. text file handling - even for UN*X, now + that there's an HB_SET_EOF flag. */ + + /* PRINTFILE is always binary and needs no special handling. */ + if( set_specifier != HB_SET_PRINTFILE ) + { + /* All other files are text files and may have an EOF + ('\x1A') character at the end (both UN*X and non-UN*X, + now that theres an HB_SET_EOF flag). */ + char cEOF = '\0'; + hb_fileSeek( handle, -1, FS_END ); /* Position to last char. */ + hb_fileRead( handle, &cEOF, 1, -1 ); /* Read the last char. */ + if( cEOF == '\x1A' ) /* If it's an EOF, */ + hb_fileSeek( handle, -1, FS_END ); /* Then write over it. */ + } + } + } + /* user RT error handler can open it too so we have to * close it again if necessary */ + if( handle == NULL ) + { + hb_xfree( szFileName ); + szFileName = NULL; + } + close_handle( pSet, set_specifier ); *handle_ptr = handle; if( *set_value ) hb_xfree( *set_value ); - *set_value = handle != NULL ? hb_strdup( szFileName ) : NULL; + *set_value = szFileName; } HB_BOOL hb_setSetCentury( HB_BOOL new_century_setting ) diff --git a/utils/hbmk2/po/hbmk2.pt_BR.po b/utils/hbmk2/po/hbmk2.pt_BR.po index dcdc6a1d4f..bec957a8fc 100644 --- a/utils/hbmk2/po/hbmk2.pt_BR.po +++ b/utils/hbmk2/po/hbmk2.pt_BR.po @@ -684,7 +684,7 @@ msgstr "(instalado)" #, c-format msgid "(not installed)" -msgstr "(não intalado)" +msgstr "(não instalado)" #, c-format msgid "Hint: Add option '%1$s' for missing function(s): %2$s"