diff --git a/ChangeLog.txt b/ChangeLog.txt index 86786789aa..329e8baaf4 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,48 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2015-09-24 22:14 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * src/rtl/hbcom.c + * src/rtl/gtcrs/gtcrs.c + * src/rtl/gtpca/gtpca.c + * src/rtl/gtstd/gtstd.c + * src/rtl/gttrm/gttrm.c + * added workaround for bug in some Linux kernels (i.e. + 3.13.0-64-generic Ubuntu) in which select() unconditionally + accepts terminal device for reading if c_cc[ VMIN ] = 0 + It's very serious problem, i.e. in GTTRM no input is possible + in such kernels without this workaround. + + * src/rtl/dirscan.prg + * modified hb_DirScan() and hb_DirRemoveAll() to work with Harbour + File IO API (hb_vf*() functions) + + added new PRG function: + hb_FileDelete( [, ] ) -> + this function removes files which match given + (it may contain path) and returns .T. if at least one file + was deleted. Optional parameter can be used to include + system ("S") and hidden ("H") files. If contains "R" + letter then before deleting READONLY attribute is removed from + files (it's necessary to remove files with READONLY attribute + in systems like DOS, MS-Windows or OS2). This function uses + Harbour File IO API (hb_vf*() functions) + * remove READONLY attribute from files in hb_DirRemoveAll() + + * include/harbour.hbx + + added hb_DirRemoveAll() and hb_FileDelete() + + * contrib/hbct/files.c + ! do not allow to remove empty directories by FileDelete() function + even if user explicitly sets directory attribute - CT3 compatible fix. + ! remove READONLY attribute before deleting READONLY files if 2-nd + parameter of FileDelete() contains READONLY bit + + * src/rtl/filesys.c + * formatting + + * ChangeLog.txt + ! typo + 2015-09-24 14:28 UTC+0200 Tamas TEVESZ (ice extreme.hu) * utils/hbmk2/hbmk2.prg + Partially merge 8f16b6731 from vszakats/harbour-core: @@ -27,7 +69,7 @@ * src/rtl/dirscan.prg + added new PRG function hb_DirRemoveAll( ) -> - BE CAREFUL! This function removed recursively whole directories + BE CAREFUL! This function removes recursively whole directories with it's body so hb_DirRemoveAll( hb_ps() ) can remove all files and directories from your disk. diff --git a/contrib/hbct/files.c b/contrib/hbct/files.c index b8a1cbe023..725a4b1ad6 100644 --- a/contrib/hbct/files.c +++ b/contrib/hbct/files.c @@ -238,15 +238,18 @@ HB_FUNC( SETFDATI ) HB_FUNC( FILEDELETE ) { - HB_BOOL bReturn = HB_FALSE; + const char * pszDirSpec = hb_parc( 1 ); + HB_BOOL fResult = HB_FALSE; - if( HB_ISCHAR( 1 ) ) + if( pszDirSpec ) { - const char * pszDirSpec = hb_parc( 1 ); - HB_FATTR ulAttr = hb_parnldef( 2, HB_FA_ALL ); + HB_FATTR nAttr = hb_parnldef( 2, HB_FA_ALL ); PHB_FFIND ffind; - if( ( ffind = hb_fsFindFirst( pszDirSpec, ulAttr ) ) != NULL ) + /* In CT3 this function does not remove directories */ + nAttr &= ~HB_FA_DIRECTORY; + + if( ( ffind = hb_fsFindFirst( pszDirSpec, nAttr ) ) != NULL ) { PHB_FNAME pFilepath; @@ -260,8 +263,15 @@ HB_FUNC( FILEDELETE ) pFilepath->szName = ffind->szName; hb_fsFNameMerge( szPath, pFilepath ); + if( ffind->attr & HB_FA_READONLY ) + { + if( nAttr & HB_FA_READONLY ) + hb_fsSetAttr( szPath, ffind->attr & ~ ( HB_FATTR ) HB_FA_READONLY ); + else + continue; + } if( hb_fsDelete( szPath ) ) - bReturn = HB_TRUE; + fResult = HB_TRUE; } while( hb_fsFindNext( ffind ) ); @@ -270,7 +280,7 @@ HB_FUNC( FILEDELETE ) } } - hb_retl( bReturn ); + hb_retl( fResult ); } HB_FUNC( FILEMOVE ) diff --git a/include/harbour.hbx b/include/harbour.hbx index 2859083242..b85f90a68b 100644 --- a/include/harbour.hbx +++ b/include/harbour.hbx @@ -410,6 +410,7 @@ DYNAMIC hb_DirCreate DYNAMIC hb_DirDelete DYNAMIC hb_Directory DYNAMIC hb_DirExists +DYNAMIC hb_DirRemoveAll DYNAMIC hb_DirScan DYNAMIC hb_DirSepAdd DYNAMIC hb_DirSepDel @@ -437,6 +438,7 @@ DYNAMIC hb_FGetDateTime DYNAMIC hb_FieldDec DYNAMIC hb_FieldLen DYNAMIC hb_FieldType +DYNAMIC hb_FileDelete DYNAMIC hb_FileExists DYNAMIC hb_FileMatch DYNAMIC hb_FIsDevice diff --git a/src/rtl/dirscan.prg b/src/rtl/dirscan.prg index cdab6162e4..c5164f8035 100644 --- a/src/rtl/dirscan.prg +++ b/src/rtl/dirscan.prg @@ -1,6 +1,6 @@ /* * Harbour Project source code: - * hb_DirScan(), hb_DirRemoveAll() + * hb_DirScan() * * Copyright 2008 Przemyslaw Czerpak * www - http://harbour-project.org @@ -47,6 +47,8 @@ */ #include "directry.ch" +#include "fileio.ch" + STATIC FUNCTION hb_doScan( cPath, cMask, cAttr, cPathSep ) @@ -54,7 +56,7 @@ STATIC FUNCTION hb_doScan( cPath, cMask, cAttr, cPathSep ) LOCAL lMatch LOCAL aResult := {} - FOR EACH aFile IN hb_Directory( cPath + hb_osFileMask(), cAttr + "D" ) + FOR EACH aFile IN hb_vfDirectory( cPath + hb_osFileMask(), cAttr + "D" ) lMatch := hb_FileMatch( aFile[ F_NAME ], cMask ) IF "D" $ aFile[ F_ATTR ] IF lMatch .AND. "D" $ cAttr @@ -73,30 +75,56 @@ STATIC FUNCTION hb_doScan( cPath, cMask, cAttr, cPathSep ) RETURN aResult FUNCTION hb_DirScan( cPath, cFileMask, cAttr ) - RETURN HB_DoScan( hb_DirSepAdd( hb_defaultValue( cPath, "" ) ), ; + RETURN hb_DoScan( hb_DirSepAdd( hb_defaultValue( cPath, "" ) ), ; iif( HB_ISSTRING( cFileMask ), cFileMask, hb_osFileMask() ), ; hb_defaultValue( cAttr, "" ), ; hb_ps() ) - FUNCTION hb_DirRemoveAll( cDir ) - LOCAL aFile, cPath + LOCAL aFile, cPath, cFile, nAttr - IF hb_DirExists( cDir ) + IF hb_vfDirExists( cDir ) cPath := hb_DirSepAdd( cDir ) - FOR EACH aFile IN hb_Directory( cPath + hb_osFileMask(), "HSDL" ) + FOR EACH aFile IN hb_vfDirectory( cPath + hb_osFileMask(), "HSDL" ) IF "D" $ aFile[ F_ATTR ] .AND. ! "L" $ aFile[ F_ATTR ] IF !( aFile[ F_NAME ] == "." .OR. aFile[ F_NAME ] == ".." .OR. aFile[ F_NAME ] == "" ) IF ! hb_DirRemoveAll( cPath + aFile[ F_NAME ] ) RETURN .F. ENDIF ENDIF - ELSEIF ! FErase( cPath + aFile[ F_NAME ] ) == 0 - RETURN .F. + ELSE + cFile := cPath + aFile[ F_NAME ] + IF "R" $ aFile[ F_ATTR ] .AND. hb_vfAttrGet( cFile, @nAttr ) + hb_vfAttrSet( cFile, hb_bitAnd( nAttr, hb_bitNot( HB_FA_READONLY ) ) ) + ENDIF + IF ! hb_vfErase( cFile ) == 0 + RETURN .F. + ENDIF ENDIF NEXT - RETURN hb_DirDelete( cDir ) == 0 + RETURN hb_vfDirRemove( cDir ) == 0 ENDIF RETURN .F. + +FUNCTION hb_FileDelete( cFileMask, cAttr ) + + LOCAL lAny := .F., aFile, cPath, cFile, cAttrMask, nAttr + + IF HB_ISSTRING( cFileMask ) .AND. ! Empty( cFileMask ) .AND. ; + ! hb_vfDirExists( cFileMask ) + cPath := hb_FNameDir( cFileMask ) + cAttrMask := StrTran( hb_defaultValue( cAttr, "" ), "D" ) + "L" + FOR EACH aFile IN hb_vfDirectory( cFileMask, cAttrMask ) + cFile := cPath + aFile[ F_NAME ] + IF "R" $ aFile[ F_ATTR ] .AND. hb_vfAttrGet( cFile, @nAttr ) + hb_vfAttrSet( cFile, hb_bitAnd( nAttr, hb_bitNot( HB_FA_READONLY ) ) ) + ENDIF + IF hb_vfErase( cFile ) == 0 + lAny := .T. + ENDIF + NEXT + ENDIF + +RETURN lAny diff --git a/src/rtl/filesys.c b/src/rtl/filesys.c index 3e6e4f4d2b..bfb692361d 100644 --- a/src/rtl/filesys.c +++ b/src/rtl/filesys.c @@ -1077,7 +1077,7 @@ HB_SIZE hb_fsPipeIsData( HB_FHANDLE hPipeHandle, HB_SIZE nBufferSize, dwAvail = 0; fResult = PeekNamedPipe( ( HANDLE ) hb_fsGetOsHandle( hPipeHandle ), NULL, 0, NULL, &dwAvail, NULL ) != 0; - if( !fResult && GetLastError() == ERROR_BROKEN_PIPE ) + if( ! fResult && GetLastError() == ERROR_BROKEN_PIPE ) { hb_fsSetError( 0 ); break; diff --git a/src/rtl/gtcrs/gtcrs.c b/src/rtl/gtcrs/gtcrs.c index ab21d8274a..67c8d53001 100644 --- a/src/rtl/gtcrs/gtcrs.c +++ b/src/rtl/gtcrs/gtcrs.c @@ -1876,6 +1876,11 @@ static InOutBase * create_ioBase( char * term, int infd, int outfd, int errfd, /* ioBase->curr_TIO.c_oflag |= ONLCR | OPOST; */ memset( ioBase->curr_TIO.c_cc, 0, NCCS ); + + /* workaround for bug in some Linux kernels (i.e. 3.13.0-64-generic + Ubuntu) in which select() unconditionally accepts stdin for + reading if c_cc[ VMIN ] = 0 [druzus] */ + ioBase->curr_TIO.c_cc[ VMIN ] = 1; } diff --git a/src/rtl/gtpca/gtpca.c b/src/rtl/gtpca/gtpca.c index 7890526cea..6dc61ade59 100644 --- a/src/rtl/gtpca/gtpca.c +++ b/src/rtl/gtpca/gtpca.c @@ -508,7 +508,14 @@ static void hb_gt_pca_Init( PHB_GT pGT, HB_FHANDLE hFilenoStdin, HB_FHANDLE hFil /* atexit( restore_input_mode ); */ s_curr_TIO.c_lflag &= ~( ICANON | ECHO ); s_curr_TIO.c_iflag &= ~ICRNL; +#if 0 s_curr_TIO.c_cc[ VMIN ] = 0; +#else + /* workaround for bug in some Linux kernels (i.e. 3.13.0-64-generic + Ubuntu) in which select() unconditionally accepts stdin for + reading if c_cc[ VMIN ] = 0 [druzus] */ + s_curr_TIO.c_cc[ VMIN ] = 1; +#endif s_curr_TIO.c_cc[ VTIME ] = 0; tcsetattr( hFilenoStdin, TCSAFLUSH, &s_curr_TIO ); diff --git a/src/rtl/gtstd/gtstd.c b/src/rtl/gtstd/gtstd.c index a623341681..a434f85bf0 100644 --- a/src/rtl/gtstd/gtstd.c +++ b/src/rtl/gtstd/gtstd.c @@ -240,7 +240,14 @@ static void hb_gt_std_Init( PHB_GT pGT, HB_FHANDLE hFilenoStdin, HB_FHANDLE hFil /* atexit( restore_input_mode ); */ pGTSTD->curr_TIO.c_lflag &= ~( ICANON | ECHO ); pGTSTD->curr_TIO.c_iflag &= ~ICRNL; +#if 0 pGTSTD->curr_TIO.c_cc[ VMIN ] = 0; +#else + /* workaround for bug in some Linux kernels (i.e. 3.13.0-64-generic + Ubuntu) in which select() unconditionally accepts stdin for + reading if c_cc[ VMIN ] = 0 [druzus] */ + pGTSTD->curr_TIO.c_cc[ VMIN ] = 1; +#endif pGTSTD->curr_TIO.c_cc[ VTIME ] = 0; tcsetattr( pGTSTD->hStdin, TCSAFLUSH, &pGTSTD->curr_TIO ); diff --git a/src/rtl/gttrm/gttrm.c b/src/rtl/gttrm/gttrm.c index ec55b1a8f0..5340709378 100644 --- a/src/rtl/gttrm/gttrm.c +++ b/src/rtl/gttrm/gttrm.c @@ -3350,6 +3350,10 @@ static void hb_gt_trm_Init( PHB_GT pGT, HB_FHANDLE hFilenoStdin, HB_FHANDLE hFil pTerm->curr_TIO.c_oflag = ONLCR | OPOST; memset( pTerm->curr_TIO.c_cc, 0, NCCS ); + /* workaround for bug in some Linux kernels (i.e. 3.13.0-64-generic + Ubuntu) in which select() unconditionally accepts stdin for + reading if c_cc[ VMIN ] = 0 [druzus] */ + pTerm->curr_TIO.c_cc[ VMIN ] = 1; /* pTerm->curr_TIO.c_cc[ VMIN ] = 0; */ /* pTerm->curr_TIO.c_cc[ VTIME ] = 0; */ tcsetattr( pTerm->hFilenoStdin, TCSAFLUSH, &pTerm->curr_TIO ); diff --git a/src/rtl/hbcom.c b/src/rtl/hbcom.c index 83b66b1198..1672a407c4 100644 --- a/src/rtl/hbcom.c +++ b/src/rtl/hbcom.c @@ -1318,7 +1318,14 @@ int hb_comInit( int iPort, int iBaud, int iParity, int iSize, int iStop ) tio.c_cflag |= ( CLOCAL | CREAD ); tio.c_cc[ VTIME ] = 0; /* inter-character timer in 1/10 sec. */ +#if 0 tio.c_cc[ VMIN ] = 0; /* minimum number of characters for read */ +#else + /* workaround for bug in some Linux kernels (i.e. 3.13.0-64-generic + Ubuntu) in which select() unconditionally accepts stdin for + reading if c_cc[ VMIN ] = 0 [druzus] */ + tio.c_cc[ VMIN ] = 1; +#endif if( iBaud ) {