From 004399c75dd8380b8ccecd85b868af1ff92a12ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Czerpak?= Date: Thu, 24 Sep 2015 22:14:14 +0200 Subject: [PATCH] 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 --- ChangeLog.txt | 44 ++++++++++++++++++++++++++++++++++++++- contrib/hbct/files.c | 24 +++++++++++++++------- include/harbour.hbx | 2 ++ src/rtl/dirscan.prg | 48 ++++++++++++++++++++++++++++++++++--------- src/rtl/filesys.c | 2 +- src/rtl/gtcrs/gtcrs.c | 5 +++++ src/rtl/gtpca/gtpca.c | 7 +++++++ src/rtl/gtstd/gtstd.c | 7 +++++++ src/rtl/gttrm/gttrm.c | 4 ++++ src/rtl/hbcom.c | 7 +++++++ 10 files changed, 131 insertions(+), 19 deletions(-) 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 ) {