2009-05-08 13:28:41 +00:00
/*
* OpenClonk , http : //www.openclonk.org
*
2009-06-05 13:41:20 +00:00
* Copyright ( c ) 1998 - 2000 , 2003 - 2004 , 2007 Matthes Bender
* Copyright ( c ) 2002 , 2004 - 2005 , 2008 Peter Wortmann
2010-12-23 00:01:24 +00:00
* Copyright ( c ) 2002 - 2003 , 2006 - 2009 Sven Eberhardt
2009-06-05 13:41:20 +00:00
* Copyright ( c ) 2004 - 2006 , 2008 G ü nther Brammer
2010-12-23 00:01:24 +00:00
* Copyright ( c ) 2009 Armin Burgmeier
* Copyright ( c ) 2009 - 2010 Nicolas Hake
* Copyright ( c ) 2010 Benjamin Herr
2009-05-08 13:28:41 +00:00
* Copyright ( c ) 2001 - 2009 , RedWolf Design GmbH , http : //www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk .
*
* Permission to use , copy , modify , and / or distribute this software for any
* purpose with or without fee is hereby granted , provided that the above
* copyright notice and this permission notice appear in all copies .
* See isc_license . txt for full license and disclaimer .
*
* " Clonk " is a registered trademark of Matthes Bender .
* See clonk_trademark_license . txt for full license .
*/
/* Linux conversion by G<> nther Brammer, 2005 */
/* Lots of file helpers */
2009-10-20 03:39:24 +00:00
# include "C4Include.h"
2009-05-08 13:28:41 +00:00
# include <StdFile.h>
# include <StdBuf.h>
# include <stdio.h>
# ifdef HAVE_IO_H
# include <io.h>
# endif
# ifdef HAVE_DIRECT_H
# include <direct.h>
# endif
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
2011-03-12 14:29:21 +00:00
# ifdef _WIN32
2011-03-13 14:48:45 +00:00
# include <C4windowswrapper.h>
2011-03-12 14:29:21 +00:00
# endif
2009-05-08 13:28:41 +00:00
# include <errno.h>
# include <stdlib.h>
# include <ctype.h>
# include <fcntl.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <zlib.h>
2009-07-10 19:33:55 +00:00
# include <string>
2009-05-08 13:28:41 +00:00
/* Path & Filename */
2009-07-22 03:12:30 +00:00
# ifdef _WIN32
static const char * DirectorySeparators = " / \\ " ;
# else
static const char * DirectorySeparators = " / " ;
# endif
2009-05-08 13:28:41 +00:00
// Return pointer to position after last backslash.
char * GetFilename ( char * szPath )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ! szPath ) return NULL ;
char * pPos , * pFilename = szPath ;
for ( pPos = szPath ; * pPos ; pPos + + ) if ( * pPos = = DirectorySeparator | | * pPos = = ' / ' ) pFilename = pPos + 1 ;
return pFilename ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
const char * GetFilename ( const char * szPath )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ! szPath ) return NULL ;
const char * pPos , * pFilename = szPath ;
for ( pPos = szPath ; * pPos ; pPos + + ) if ( * pPos = = DirectorySeparator | | * pPos = = ' / ' ) pFilename = pPos + 1 ;
return pFilename ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
const char * GetFilenameOnly ( const char * strFilename )
{
// Get filename to static buffer
static char strBuffer [ _MAX_PATH + 1 ] ;
SCopy ( GetFilename ( strFilename ) , strBuffer ) ;
// Truncate extension
RemoveExtension ( strBuffer ) ;
// Return buffer
return strBuffer ;
}
const char * GetC4Filename ( const char * szPath )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// returns path to file starting at first .c4*-directory.
if ( ! szPath ) return NULL ;
const char * pPos , * pFilename = szPath ;
for ( pPos = szPath ; * pPos ; pPos + + )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( * pPos = = DirectorySeparator | | * pPos = = ' / ' )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pPos > = szPath + 4 & & SEqual2NoCase ( pPos - 4 , " .c4 " ) ) return pFilename ;
pFilename = pPos + 1 ;
}
}
2010-03-28 18:58:01 +00:00
return pFilename ;
}
2009-05-08 13:28:41 +00:00
int GetTrailingNumber ( const char * strString )
{
// Default
int iNumber = 0 ;
// Start from end
const char * cpPos = strString + SLen ( strString ) ;
// Walk back while number
while ( ( cpPos > strString ) & & Inside ( * ( cpPos - 1 ) , ' 0 ' , ' 9 ' ) ) cpPos - - ;
// Scan number
sscanf ( cpPos , " %d " , & iNumber ) ;
// Return result
return iNumber ;
}
// Like GetFilename, but searches for a slash instead of a backslash
// (unix-style paths)
char * GetFilenameWeb ( char * szPath )
2010-03-28 18:58:01 +00:00
{
if ( ! szPath ) return NULL ;
2009-05-08 13:28:41 +00:00
char * pPos , * pFilename = szPath ;
for ( pPos = szPath ; * pPos ; pPos + + ) if ( * pPos = = ' / ' ) pFilename = pPos + 1 ;
return pFilename ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
const char * GetFilenameWeb ( const char * szPath )
2010-03-28 18:58:01 +00:00
{
if ( ! szPath ) return NULL ;
2009-05-08 13:28:41 +00:00
const char * pPos , * pFilename = szPath ;
for ( pPos = szPath ; * pPos ; pPos + + ) if ( * pPos = = ' / ' ) pFilename = pPos + 1 ;
return pFilename ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Return pointer to last file extension.
char * GetExtension ( char * szFilename )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
int pos , end ;
for ( end = 0 ; szFilename [ end ] ; end + + ) { }
pos = end ;
while ( ( pos > 0 ) & & ( szFilename [ pos - 1 ] ! = ' . ' ) & & ( szFilename [ pos - 1 ] ! = DirectorySeparator ) ) - - pos ;
if ( ( pos > 0 ) & & szFilename [ pos - 1 ] = = ' . ' ) return szFilename + pos ;
return szFilename + end ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
const char * GetExtension ( const char * szFilename )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
int pos , end ;
for ( end = 0 ; szFilename [ end ] ; end + + ) { }
pos = end ;
while ( ( pos > 0 ) & & ( szFilename [ pos - 1 ] ! = ' . ' ) & & ( szFilename [ pos - 1 ] ! = DirectorySeparator ) ) pos - - ;
if ( szFilename [ pos - 1 ] = = ' . ' ) return szFilename + pos ;
return szFilename + end ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void RealPath ( const char * szFilename , char * pFullFilename )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
# ifdef _WIN32
_fullpath ( pFullFilename , szFilename , _MAX_PATH ) ;
# else
2010-03-27 16:05:02 +00:00
char * pSuffix = NULL ;
2009-05-08 13:28:41 +00:00
char szCopy [ _MAX_PATH + 1 ] ;
2010-03-28 18:58:01 +00:00
for ( ; ; )
{
2009-05-08 13:28:41 +00:00
// Try to convert to full filename. Note this might fail if the given file doesn't exist
2010-03-28 18:58:01 +00:00
if ( realpath ( szFilename , pFullFilename ) )
2009-05-08 13:28:41 +00:00
break ;
2010-03-27 16:05:02 +00:00
// ... which is undesired behaviour here. Try to reduce the filename until it works.
2010-03-28 18:58:01 +00:00
if ( ! pSuffix )
{
2009-05-08 13:28:41 +00:00
SCopy ( szFilename , szCopy , _MAX_PATH ) ;
szFilename = szCopy ;
pSuffix = szCopy + SLen ( szCopy ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
* pSuffix = ' / ' ;
2010-03-28 18:58:01 +00:00
while ( pSuffix > = szCopy )
if ( * - - pSuffix = = ' / ' )
2009-05-08 13:28:41 +00:00
break ;
2010-03-28 18:58:01 +00:00
if ( pSuffix < szCopy )
{
2009-05-08 13:28:41 +00:00
// Give up: Just copy whatever we got
SCopy ( szFilename , pFullFilename , _MAX_PATH ) ;
return ;
}
2010-03-28 18:58:01 +00:00
* pSuffix = 0 ;
}
2009-05-08 13:28:41 +00:00
// Append suffix
2010-03-28 18:58:01 +00:00
if ( pSuffix )
{
* pSuffix = ' / ' ;
2009-05-08 13:28:41 +00:00
SAppend ( pSuffix , pFullFilename , _MAX_PATH ) ;
}
2010-03-28 18:58:01 +00:00
# endif
}
2009-05-08 13:28:41 +00:00
// Copy (extended) parent path (without backslash) to target buffer.
bool GetParentPath ( const char * szFilename , char * szBuffer )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Prepare filename
SCopy ( szFilename , szBuffer , _MAX_PATH ) ;
// Extend relative single filenames
2010-03-28 18:58:01 +00:00
# ifdef _WIN32
2009-05-08 13:28:41 +00:00
if ( ! SCharCount ( DirectorySeparator , szFilename ) ) _fullpath ( szBuffer , szFilename , _MAX_PATH ) ;
2010-03-28 18:58:01 +00:00
# else
2009-05-08 13:28:41 +00:00
if ( ! SCharCount ( DirectorySeparator , szFilename ) ) RealPath ( szFilename , szBuffer ) ;
2010-03-28 18:58:01 +00:00
# endif
2009-05-08 13:28:41 +00:00
// Truncate path
return TruncatePath ( szBuffer ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool GetParentPath ( const char * szFilename , StdStrBuf * outBuf )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
char buf [ _MAX_PATH + 1 ] ; * buf = ' \0 ' ;
if ( ! GetParentPath ( szFilename , buf ) ) return false ;
outBuf - > Copy ( buf ) ;
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool GetRelativePath ( const char * strPath , const char * strRelativeTo , char * strBuffer , int iBufferSize )
{
// Specified path is relative to base path
// Copy relative section
const char * szCpy ;
SCopy ( szCpy = GetRelativePathS ( strPath , strRelativeTo ) , strBuffer , iBufferSize ) ;
// return whether it was made relative
return szCpy ! = strPath ;
}
const char * GetRelativePathS ( const char * strPath , const char * strRelativeTo )
{
// Specified path is relative to base path
2010-03-28 18:58:01 +00:00
# ifdef _WIN32
2009-05-08 13:28:41 +00:00
if ( SEqual2NoCase ( strPath , strRelativeTo ) )
2010-03-28 18:58:01 +00:00
# else
2009-05-08 13:28:41 +00:00
if ( SEqual2 ( strPath , strRelativeTo ) )
2010-03-28 18:58:01 +00:00
# endif
2009-05-08 13:28:41 +00:00
{
// return relative section
return strPath + SLen ( strRelativeTo ) + ( ( strPath [ SLen ( strRelativeTo ) ] = = DirectorySeparator ) ? + 1 : 0 ) ;
}
// Not relative: return full path
return strPath ;
}
bool IsGlobalPath ( const char * szPath )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
# ifdef _WIN32
// C:\...
if ( * szPath & & szPath [ 1 ] = = ' : ' ) return true ;
# endif
// /usr/bin, \Temp\, ...
if ( * szPath = = DirectorySeparator ) return true ;
return false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Truncate string before last backslash.
2010-03-28 18:58:01 +00:00
bool TruncatePath ( char * szPath )
{
2009-05-08 13:28:41 +00:00
if ( ! szPath ) return false ;
int iBSPos ;
iBSPos = SCharLastPos ( DirectorySeparator , szPath ) ;
# ifndef _WIN32
int iBSPos2 ;
iBSPos2 = SCharLastPos ( ' \\ ' , szPath ) ;
if ( iBSPos2 > iBSPos ) fprintf ( stderr , " Warning: TruncatePath with a \\ (%s) \n " , szPath ) ;
# endif
if ( iBSPos < 0 ) return false ;
szPath [ iBSPos ] = 0 ;
return true ;
}
// Append terminating backslash if not present.
void AppendBackslash ( char * szFilename )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
int i = SLen ( szFilename ) ;
if ( i > 0 ) if ( ( szFilename [ i - 1 ] = = DirectorySeparator ) ) return ;
SAppendChar ( DirectorySeparator , szFilename ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Remove terminating backslash if present.
void TruncateBackslash ( char * szFilename )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
int i = SLen ( szFilename ) ;
if ( i > 0 ) if ( ( szFilename [ i - 1 ] = = DirectorySeparator ) ) szFilename [ i - 1 ] = 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Append extension if no extension.
void DefaultExtension ( char * szFilename , const char * szExtension )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
if ( ! ( * GetExtension ( szFilename ) ) )
{ SAppend ( " . " , szFilename ) ; SAppend ( szExtension , szFilename ) ; }
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void DefaultExtension ( StdStrBuf * sFilename , const char * szExtension )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
assert ( sFilename ) ;
2010-03-27 16:05:02 +00:00
if ( ! ( * GetExtension ( sFilename - > getData ( ) ) ) )
{ sFilename - > AppendChar ( ' . ' ) ; sFilename - > Append ( szExtension ) ; }
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Append or overwrite extension.
void EnforceExtension ( char * szFilename , const char * szExtension )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
char * ext = GetExtension ( szFilename ) ;
2010-03-28 18:58:01 +00:00
if ( ext [ 0 ] ) { SCopy ( szExtension , ext ) ; }
2009-05-08 13:28:41 +00:00
else { SAppend ( " . " , szFilename ) ; SAppend ( szExtension , szFilename ) ; }
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void EnforceExtension ( StdStrBuf * sFilename , const char * szExtension )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
assert ( sFilename ) ;
const char * ext = GetExtension ( sFilename - > getData ( ) ) ;
2010-03-28 18:58:01 +00:00
if ( ext [ 0 ] ) { sFilename - > ReplaceEnd ( ext - sFilename - > getData ( ) , szExtension ) ; }
2009-05-08 13:28:41 +00:00
else { sFilename - > AppendChar ( ' . ' ) ; sFilename - > Append ( szExtension ) ; }
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// remove extension
void RemoveExtension ( char * szFilename )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
char * ext = GetExtension ( szFilename ) ;
2010-03-27 16:05:02 +00:00
if ( ext [ 0 ] ) ext [ - 1 ] = 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void RemoveExtension ( StdStrBuf * psFileName )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( psFileName & & * psFileName )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
RemoveExtension ( psFileName - > getMData ( ) ) ;
psFileName - > SetLength ( strlen ( psFileName - > getData ( ) ) ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Enforce indexed extension until item does not exist.
void MakeTempFilename ( char * szFilename )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
DefaultExtension ( szFilename , " tmp " ) ;
char * fn_ext = GetExtension ( szFilename ) ;
int cnum = - 1 ;
do
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
cnum + + ;
osprintf ( fn_ext , " %03d " , cnum ) ;
}
2010-03-28 18:58:01 +00:00
while ( FileExists ( szFilename ) & & ( cnum < 999 ) ) ;
}
2009-05-08 13:28:41 +00:00
void MakeTempFilename ( StdStrBuf * sFilename )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
assert ( sFilename ) ;
if ( ! sFilename - > getLength ( ) ) sFilename - > Copy ( " temp.tmp " ) ;
EnforceExtension ( sFilename , " tmp " ) ;
2010-03-27 16:05:02 +00:00
char * fn_ext = GetExtension ( sFilename - > getMData ( ) ) ;
int cnum = - 1 ;
do
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
cnum + + ;
osprintf ( fn_ext , " %03d " , cnum ) ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
while ( FileExists ( sFilename - > getData ( ) ) & & ( cnum < 999 ) ) ;
}
2009-05-08 13:28:41 +00:00
bool WildcardListMatch ( const char * szWildcardList , const char * szString )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety
2010-03-28 18:58:01 +00:00
if ( ! szString | | ! szWildcardList ) return false ;
2009-05-08 13:28:41 +00:00
// match any item in list
StdStrBuf sWildcard , sWildcardList ( szWildcardList ) ;
int32_t i = 0 ;
while ( sWildcardList . GetSection ( i + + , & sWildcard , ' | ' ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( WildcardMatch ( sWildcard . getData ( ) , szString ) ) return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// none matched
return false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2009-06-16 00:38:39 +00:00
bool IsWildcardString ( const char * szString )
2010-03-28 18:58:01 +00:00
{
2009-06-16 00:38:39 +00:00
// safety
2010-03-28 18:58:01 +00:00
if ( ! szString ) return false ;
2009-06-16 00:38:39 +00:00
// known wildcard characters: *?
return ( SCharCount ( ' ? ' , szString ) > 0 ) | | ( SCharCount ( ' * ' , szString ) > 0 ) ;
2010-03-28 18:58:01 +00:00
}
2009-06-16 00:38:39 +00:00
2009-05-08 13:28:41 +00:00
bool WildcardMatch ( const char * szWildcard , const char * szString )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety
2010-03-28 18:58:01 +00:00
if ( ! szString | | ! szWildcard ) return false ;
2010-03-27 16:05:02 +00:00
// match char-wise
const char * pWild = szWildcard , * pPos = szString ;
const char * pLWild = NULL , * pLPos = NULL ; // backtracking
2010-03-28 18:58:01 +00:00
while ( * pWild | | pLWild )
2010-03-27 16:05:02 +00:00
// string wildcard?
2010-03-28 18:58:01 +00:00
if ( * pWild = = ' * ' )
2010-03-27 16:05:02 +00:00
{ pLWild = + + pWild ; pLPos = pPos ; }
2010-03-28 18:58:01 +00:00
// nothing left to match?
else if ( ! * pPos )
2010-03-27 16:05:02 +00:00
break ;
2010-03-28 18:58:01 +00:00
// equal or one-character-wildcard? proceed
else if ( * pWild = = ' ? ' | | tolower ( * pWild ) = = tolower ( * pPos ) )
2010-03-27 16:05:02 +00:00
{ pWild + + ; pPos + + ; }
2010-03-28 18:58:01 +00:00
// backtrack possible?
else if ( pLPos )
2010-03-27 16:05:02 +00:00
{ pWild = pLWild ; pPos = + + pLPos ; }
2010-03-28 18:58:01 +00:00
// match failed
2010-03-27 16:05:02 +00:00
else
return false ;
// match complete if both strings are fully matched
return ! * pWild & & ! * pPos ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
# define SStripChars "!\"<22> %& / =?+*#:;<>\\."
// create a valid file name from some title
void MakeFilenameFromTitle ( char * szTitle )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// copy all chars but those to be stripped
char * szFilename = szTitle , * szTitle2 = szTitle ;
while ( * szTitle2 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
bool fStrip ;
if ( IsWhiteSpace ( * szTitle2 ) )
fStrip = ( szFilename = = szTitle ) ;
else
fStrip = ( SCharPos ( * szTitle2 , SStripChars ) > = 0 ) ;
if ( ! fStrip ) * szFilename + + = * szTitle2 ;
+ + szTitle2 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// truncate spaces from end
while ( IsWhiteSpace ( * - - szFilename ) ) if ( szFilename = = szTitle ) { - - szFilename ; break ; }
// terminate
* + + szFilename = 0 ;
// no name? (only invalid chars)
if ( ! * szTitle ) SCopy ( " unnamed " , szTitle , 50 ) ;
// done
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
/* Files */
bool FileExists ( const char * szFilename )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
return ( ! access ( szFilename , F_OK ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
size_t FileSize ( const char * szFilename )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
struct stat stStats ;
if ( stat ( szFilename , & stStats ) ) return 0 ;
return stStats . st_size ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// operates on a filedescriptor from open or fileno
size_t FileSize ( int fdes )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
# ifdef _WIN32
return filelength ( fdes ) ;
# else
struct stat stStats ;
if ( fstat ( fdes , & stStats ) ) return 0 ;
return stStats . st_size ;
# endif
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
int FileTime ( const char * szFilename )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
struct stat stStats ;
if ( stat ( szFilename , & stStats ) ! = 0 ) return 0 ;
return stStats . st_mtime ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool EraseFile ( const char * szFilename )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
//chmod(szFilename,200);
# ifdef _WIN32
SetFileAttributes ( szFilename , FILE_ATTRIBUTE_NORMAL ) ;
# endif
// either unlink or remove could be used. Well, stick to ANSI C where possible.
if ( remove ( szFilename ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( errno = = ENOENT )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Hah, here the wrapper actually makes sense:
// The engine only cares about the file not being there after this call.
return true ;
}
2010-03-28 18:58:01 +00:00
return false ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
return true ;
}
2009-05-08 13:28:41 +00:00
bool EraseFiles ( const char * szFilePath )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
return ForEachFile ( szFilePath , & EraseFile ) > 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
# ifndef _WIN32
bool CopyFile ( const char * szSource , const char * szTarget , bool FailIfExists )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int fds = open ( szSource , O_RDONLY ) ;
if ( ! fds ) return false ;
struct stat info ; fstat ( fds , & info ) ;
int fdt = open ( szTarget , O_WRONLY | O_CREAT | ( FailIfExists ? O_EXCL : O_TRUNC ) , info . st_mode ) ;
if ( ! fdt )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
close ( fds ) ;
return false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
char buffer [ 1024 ] ; ssize_t l ;
2010-01-25 04:00:59 +00:00
while ( ( l = read ( fds , buffer , sizeof ( buffer ) ) ) > 0 )
if ( write ( fdt , buffer , l ) < l )
2010-03-28 18:58:01 +00:00
{
l = - 1 ;
break ;
}
2009-05-08 13:28:41 +00:00
close ( fds ) ;
close ( fdt ) ;
// On error, return false
return l ! = - 1 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
# endif
bool RenameFile ( const char * szFilename , const char * szNewFilename )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( rename ( szFilename , szNewFilename ) < 0 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( CopyFile ( szFilename , szNewFilename , false ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
return EraseFile ( szFilename ) ;
}
2010-03-28 18:58:01 +00:00
return false ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
return true ;
}
2009-05-08 13:28:41 +00:00
bool MakeOriginalFilename ( char * szFilename )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety
if ( ! szFilename ) return false ;
# ifdef _WIN32
// root-directory?
2010-04-21 19:12:49 +00:00
if ( Inside ( SLen ( szFilename ) , 2u , 3u ) ) if ( szFilename [ 1 ] = = ' : ' )
2009-05-08 13:28:41 +00:00
{
2010-03-28 18:58:01 +00:00
szFilename [ 2 ] = ' \\ ' ; szFilename [ 3 ] = 0 ;
if ( GetDriveType ( szFilename ) = = DRIVE_NO_ROOT_DIR ) return false ;
return true ;
2009-05-08 13:28:41 +00:00
}
struct _finddata_t fdt ; long shnd ;
if ( ( shnd = _findfirst ( ( char * ) szFilename , & fdt ) ) < 0 ) return false ;
_findclose ( shnd ) ;
SCopy ( GetFilename ( fdt . name ) , GetFilename ( szFilename ) , _MAX_FNAME ) ;
# else
2010-03-28 18:58:01 +00:00
if ( SCharPos ( ' * ' , szFilename ) ! = - 1 )
{
2009-05-08 13:28:41 +00:00
fputs ( " Warning: MakeOriginalFilename with \" " , stderr ) ;
fputs ( szFilename , stderr ) ;
fputs ( " \" ! \n " , stderr ) ;
}
# endif
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
/* Directories */
const char * GetWorkingDirectory ( )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
static char buf [ _MAX_PATH + 1 ] ;
return getcwd ( buf , _MAX_PATH ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool SetWorkingDirectory ( const char * path )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
# ifdef _WIN32
2010-03-27 16:05:02 +00:00
return SetCurrentDirectory ( path ) ! = 0 ;
2009-05-08 13:28:41 +00:00
# else
2010-03-27 16:05:02 +00:00
return ( chdir ( path ) = = 0 ) ;
2009-05-08 13:28:41 +00:00
# endif
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2009-07-10 19:33:55 +00:00
bool CreatePath ( const std : : string & path )
{
assert ( ! path . empty ( ) ) ;
# ifdef _WIN32
2009-07-11 18:03:12 +00:00
if ( CreateDirectory ( path . c_str ( ) , NULL ) )
2009-06-06 15:20:17 +00:00
{
2009-07-11 18:03:12 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
else
{
2009-07-10 19:33:55 +00:00
DWORD err = GetLastError ( ) ;
2010-03-28 18:58:01 +00:00
switch ( err )
2009-06-06 15:20:17 +00:00
{
2009-07-10 19:33:55 +00:00
case ERROR_PATH_NOT_FOUND :
break ;
case ERROR_ALREADY_EXISTS :
return true ;
default :
// Something major has happened: Log
2010-03-28 18:58:01 +00:00
{
LPSTR str ;
if ( FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS ,
NULL , err , 0 , ( LPSTR ) & str , 0 , NULL ) )
2009-06-06 15:20:17 +00:00
{
2010-03-28 18:58:01 +00:00
LogF ( " CreateDirectory failed: %s " , str ) ;
LocalFree ( str ) ;
2009-06-06 15:20:17 +00:00
}
2010-03-28 18:58:01 +00:00
return false ;
}
2009-06-06 15:20:17 +00:00
}
2009-07-10 19:33:55 +00:00
}
# else
if ( ! mkdir ( path . c_str ( ) , S_IREAD | S_IWRITE | S_IEXEC ) )
return true ;
2010-03-28 18:58:01 +00:00
switch ( errno )
2009-07-10 19:33:55 +00:00
{
case ENOENT :
break ;
case EEXIST :
// FIXME: Check whether the path is blocked by a non-directory
return true ;
default :
return false ;
2009-06-06 15:20:17 +00:00
}
2009-05-08 13:28:41 +00:00
# endif
2009-07-10 19:33:55 +00:00
// Recursively create parent path
std : : string : : size_type slash = path . find_last_of ( DirectorySeparators ) ;
if ( slash = = 0 | | slash = = std : : string : : npos )
return false ;
return CreatePath ( path . substr ( 0 , slash ) ) & & CreatePath ( path ) ;
}
2009-05-08 13:28:41 +00:00
bool DirectoryExists ( const char * szFilename )
2010-03-28 18:58:01 +00:00
{
2009-09-23 02:09:13 +00:00
// Ignore trailing slash or backslash, except when we are probing the
// root directory '/'.
2009-05-08 13:28:41 +00:00
char bufFilename [ _MAX_PATH + 1 ] ;
if ( szFilename & & szFilename [ 0 ] )
2009-09-23 02:09:13 +00:00
{
unsigned int len = SLen ( szFilename ) ;
if ( len > 1 & & ( ( szFilename [ len - 1 ] = = ' \\ ' ) | | ( szFilename [ len - 1 ] = = ' / ' ) ) )
2009-05-08 13:28:41 +00:00
{
SCopy ( szFilename , bufFilename , _MAX_PATH ) ;
bufFilename [ SLen ( bufFilename ) - 1 ] = 0 ;
szFilename = bufFilename ;
}
2009-09-23 02:09:13 +00:00
}
2009-05-08 13:28:41 +00:00
// Check file attributes
# ifdef _WIN32
struct _finddata_t fdt ; int shnd ;
if ( ( shnd = _findfirst ( szFilename , & fdt ) ) < 0 ) return false ;
_findclose ( shnd ) ;
if ( fdt . attrib & _A_SUBDIR ) return true ;
# else
struct stat stStats ;
if ( stat ( szFilename , & stStats ) ! = 0 ) return 0 ;
return ( S_ISDIR ( stStats . st_mode ) ) ;
# endif
return false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2010-03-28 18:58:01 +00:00
bool CopyDirectory ( const char * szSource , const char * szTarget , bool fResetAttributes )
{
2009-05-08 13:28:41 +00:00
// Source check
if ( ! szSource | | ! szTarget ) return false ;
if ( ! DirectoryExists ( szSource ) ) return false ;
// Do not process system navigation directories
if ( SEqual ( GetFilename ( szSource ) , " . " )
2010-03-28 18:58:01 +00:00
| | SEqual ( GetFilename ( szSource ) , " .. " ) )
2009-05-08 13:28:41 +00:00
return true ;
// Overwrite target
//if (ItemExists(szTarget))
if ( ! EraseItem ( szTarget ) ) return false ;
// Create target directory
bool status = true ;
2010-03-28 18:58:01 +00:00
# ifdef _WIN32
2009-05-08 13:28:41 +00:00
if ( _mkdir ( szTarget ) ! = 0 ) return false ;
// Copy contents to target directory
char contents [ _MAX_PATH + 1 ] ;
SCopy ( szSource , contents ) ; AppendBackslash ( contents ) ;
SAppend ( " * " , contents ) ;
_finddata_t fdt ; int hfdt ;
2010-03-28 18:58:01 +00:00
if ( ( hfdt = _findfirst ( contents , & fdt ) ) > - 1 )
{
do
{
2009-05-08 13:28:41 +00:00
char itemsource [ _MAX_PATH + 1 ] , itemtarget [ _MAX_PATH + 1 ] ;
SCopy ( szSource , itemsource ) ; AppendBackslash ( itemsource ) ; SAppend ( fdt . name , itemsource ) ;
SCopy ( szTarget , itemtarget ) ; AppendBackslash ( itemtarget ) ; SAppend ( fdt . name , itemtarget ) ;
if ( ! CopyItem ( itemsource , itemtarget , fResetAttributes ) ) status = false ;
}
while ( _findnext ( hfdt , & fdt ) = = 0 ) ;
_findclose ( hfdt ) ;
}
2010-03-28 18:58:01 +00:00
# else
2009-05-08 13:28:41 +00:00
if ( mkdir ( szTarget , 0777 ) ! = 0 ) return false ;
DIR * d = opendir ( szSource ) ;
dirent * ent ;
char itemsource [ _MAX_PATH + 1 ] , itemtarget [ _MAX_PATH + 1 ] ;
2010-03-28 18:58:01 +00:00
while ( ( ent = readdir ( d ) ) )
{
2009-05-08 13:28:41 +00:00
SCopy ( szSource , itemsource ) ; AppendBackslash ( itemsource ) ; SAppend ( ent - > d_name , itemsource ) ;
SCopy ( szTarget , itemtarget ) ; AppendBackslash ( itemtarget ) ; SAppend ( ent - > d_name , itemtarget ) ;
if ( ! CopyItem ( itemsource , itemtarget , fResetAttributes ) ) status = false ;
}
closedir ( d ) ;
2010-03-28 18:58:01 +00:00
# endif
2009-05-08 13:28:41 +00:00
return status ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2010-03-28 18:58:01 +00:00
bool EraseDirectory ( const char * szDirName )
{
2009-05-08 13:28:41 +00:00
// Do not process system navigation directories
if ( SEqual ( GetFilename ( szDirName ) , " . " )
2010-03-28 18:58:01 +00:00
| | SEqual ( GetFilename ( szDirName ) , " .. " ) )
2009-05-08 13:28:41 +00:00
return true ;
char path [ _MAX_PATH + 1 ] ;
# ifdef _WIN32
// Get path to directory contents
SCopy ( szDirName , path ) ; SAppend ( " \\ *.* " , path ) ;
// Erase subdirectories and files
ForEachFile ( path , & EraseItem ) ;
# else
DIR * d = opendir ( szDirName ) ;
dirent * ent ;
2010-03-28 18:58:01 +00:00
while ( ( ent = readdir ( d ) ) )
{
2009-05-08 13:28:41 +00:00
SCopy ( szDirName , path ) ; AppendBackslash ( path ) ; SAppend ( ent - > d_name , path ) ;
if ( ! EraseItem ( path ) ) return false ;
}
closedir ( d ) ;
# endif
// Check working directory
2010-03-28 18:58:01 +00:00
if ( SEqual ( szDirName , GetWorkingDirectory ( ) ) )
{
2009-05-08 13:28:41 +00:00
// Will work only if szDirName is full path and correct case!
SCopy ( GetWorkingDirectory ( ) , path ) ;
int lbacks = SCharLastPos ( DirectorySeparator , path ) ;
2010-03-28 18:58:01 +00:00
if ( lbacks > - 1 )
{
2009-05-08 13:28:41 +00:00
path [ lbacks ] = 0 ; SetWorkingDirectory ( path ) ;
}
}
// Remove directory
//chmod(szDirName,200);
# ifdef _WIN32
return ! ! RemoveDirectory ( szDirName ) ;
# else
return ( rmdir ( szDirName ) = = 0 | | errno = = ENOENT ) ;
# endif
}
/* Items */
/*int ItemAttributes(const char *szItemName)
2010-03-28 18:58:01 +00:00
{
return FileAttributes ( szItemName ) ;
} */
2009-05-08 13:28:41 +00:00
bool RenameItem ( const char * szItemName , const char * szNewItemName )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// FIXME: What if the directory would have to be copied?
return RenameFile ( szItemName , szNewItemName ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool EraseItem ( const char * szItemName )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
if ( ! EraseFile ( szItemName ) ) return EraseDirectory ( szItemName ) ;
else return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool CreateItem ( const char * szItemname )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Overwrite any old item
EraseItem ( szItemname ) ;
// Create dummy item
2010-03-27 16:05:02 +00:00
FILE * fhnd ;
if ( ! ( fhnd = fopen ( szItemname , " wb " ) ) ) return false ;
fclose ( fhnd ) ;
2009-05-08 13:28:41 +00:00
// Success
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
# ifdef _WIN32
bool EraseItems ( const char * szItemPath )
2010-03-28 18:58:01 +00:00
{
2010-03-27 16:05:02 +00:00
return ForEachFile ( szItemPath , & EraseItem ) > 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
# endif
bool CopyItem ( const char * szSource , const char * szTarget , bool fResetAttributes )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Check for identical source and target
if ( ItemIdentical ( szSource , szTarget ) ) return true ;
// Copy directory
if ( DirectoryExists ( szSource ) )
return CopyDirectory ( szSource , szTarget , fResetAttributes ) ;
// Copy file
if ( ! CopyFile ( szSource , szTarget , false ) ) return false ;
// Reset any attributes if desired
# ifdef _WIN32
if ( fResetAttributes ) if ( ! SetFileAttributes ( szTarget , FILE_ATTRIBUTE_NORMAL ) ) return false ;
# else
if ( fResetAttributes ) if ( chmod ( szTarget , S_IRWXU ) ) return false ;
# endif
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool MoveItem ( const char * szSource , const char * szTarget )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ItemIdentical ( szSource , szTarget ) ) return true ;
return RenameFile ( szSource , szTarget ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool ItemIdentical ( const char * szFilename1 , const char * szFilename2 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
char szFullFile1 [ _MAX_PATH + 1 ] , szFullFile2 [ _MAX_PATH + 1 ] ;
RealPath ( szFilename1 , szFullFile1 ) ; RealPath ( szFilename2 , szFullFile2 ) ;
# ifdef _WIN32
if ( SEqualNoCase ( szFullFile1 , szFullFile2 ) ) return true ;
# else
if ( SEqual ( szFullFile1 , szFullFile2 ) ) return true ;
# endif
return false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
//------------------------- Multi File Processing --------------------------------------------------------------------------------------------------------
2010-01-25 15:54:38 +00:00
struct DirectoryIteratorP
{
DirectoryIteratorP ( ) : ref ( 1 ) { }
DirectoryIterator : : FileList files ;
std : : string directory ;
int ref ;
} ;
DirectoryIterator : : DirectoryIterator ( )
2010-03-28 18:58:01 +00:00
: p ( new DirectoryIteratorP ) , iter ( p - > files . end ( ) )
2010-01-25 15:54:38 +00:00
{ }
DirectoryIterator : : DirectoryIterator ( const DirectoryIterator & other )
2010-03-28 18:58:01 +00:00
: p ( other . p ) , iter ( p - > files . begin ( ) )
2010-01-25 15:54:38 +00:00
{
+ + p - > ref ;
}
DirectoryIterator : : ~ DirectoryIterator ( )
{
if ( - - p - > ref = = 0 )
delete p ;
}
2009-05-08 13:28:41 +00:00
2010-01-25 15:54:38 +00:00
void DirectoryIterator : : Reset ( )
{
iter = p - > files . begin ( ) ;
2009-05-08 13:28:41 +00:00
}
2010-01-25 15:54:38 +00:00
void DirectoryIterator : : Reset ( const char * dirname )
{
if ( p - > directory = = dirname )
{
// Skip reinitialisation and just reset the iterator
iter = p - > files . begin ( ) ;
return ;
2009-05-08 13:28:41 +00:00
}
2010-01-25 15:54:38 +00:00
if ( p - > ref > 1 )
{
// Detach from shared memory
- - p - > ref ;
p = new DirectoryIteratorP ;
2009-05-08 13:28:41 +00:00
}
2010-01-25 15:54:38 +00:00
p - > files . clear ( ) ;
iter = p - > files . end ( ) ;
Read ( dirname ) ;
2009-05-08 13:28:41 +00:00
}
2010-01-25 15:54:38 +00:00
DirectoryIterator : : DirectoryIterator ( const char * dirname )
2010-03-28 18:58:01 +00:00
: p ( new DirectoryIteratorP ) , iter ( p - > files . end ( ) )
2010-01-25 15:54:38 +00:00
{
Read ( dirname ) ;
2009-05-08 13:28:41 +00:00
}
2010-01-25 15:54:38 +00:00
void DirectoryIterator : : Read ( const char * dirname )
{
assert ( dirname & & * dirname ) ;
assert ( p - > files . empty ( ) ) ;
std : : string search_path ( dirname ) ;
search_path . push_back ( DirectorySeparator ) ;
# ifdef WIN32
WIN32_FIND_DATA file = { 0 } ;
HANDLE fh = FindFirstFile ( ( search_path + ' * ' ) . c_str ( ) , & file ) ;
if ( fh = = INVALID_HANDLE_VALUE )
{
switch ( GetLastError ( ) )
{
case ERROR_FILE_NOT_FOUND :
// This is okay, either the directory doesn't exist or there are no files
return ;
default :
// Something else broke
throw std : : runtime_error ( " DirectoryIterator::Read(const char*): Unable to read file system " ) ;
}
2009-05-08 13:28:41 +00:00
}
2010-01-25 15:54:38 +00:00
// Insert files into list
do
{
// ...unless they're . or ..
if ( file . cFileName [ 0 ] = = ' . ' & & ( file . cFileName [ 1 ] = = ' \0 ' | | ( file . cFileName [ 1 ] = = ' . ' & & file . cFileName [ 2 ] = = ' \0 ' ) ) )
continue ;
p - > files . push_back ( file . cFileName ) ;
2010-03-28 18:58:01 +00:00
}
while ( FindNextFile ( fh , & file ) ) ;
2010-01-25 15:54:38 +00:00
FindClose ( fh ) ;
2009-05-08 13:28:41 +00:00
# else
2010-01-25 15:54:38 +00:00
DIR * fh = opendir ( dirname ) ;
if ( fh = = NULL )
{
switch ( errno )
{
case ENOENT :
case ENOTDIR :
// Okay, so there's no files here.
return ;
default :
// Something else broke
throw std : : runtime_error ( " DirectoryIterator::Read(const char*): Unable to read file system " ) ;
}
2009-05-08 13:28:41 +00:00
}
2010-01-25 15:54:38 +00:00
dirent * file ;
// Insert files into list
while ( ( file = readdir ( fh ) ) ! = NULL )
{
// ...unless they're . or ..
if ( file - > d_name [ 0 ] = = ' . ' & & ( file - > d_name [ 1 ] = = ' \0 ' | | ( file - > d_name [ 1 ] = = ' . ' & & file - > d_name [ 2 ] = = ' \0 ' ) ) )
continue ;
2010-01-25 19:17:29 +00:00
p - > files . push_back ( file - > d_name ) ;
2010-01-25 15:54:38 +00:00
}
closedir ( fh ) ;
# endif
// Sort list
std : : sort ( p - > files . begin ( ) , p - > files . end ( ) ) ;
for ( FileList : : iterator it = p - > files . begin ( ) ; it ! = p - > files . end ( ) ; + + it )
it - > insert ( 0 , search_path ) ; // prepend path to all file entries
iter = p - > files . begin ( ) ;
p - > directory = dirname ;
2009-05-08 13:28:41 +00:00
}
2010-01-25 15:54:38 +00:00
DirectoryIterator & DirectoryIterator : : operator + + ( )
{
2010-03-28 18:58:01 +00:00
if ( iter ! = p - > files . end ( ) )
2010-01-25 15:54:38 +00:00
+ + iter ;
2009-05-08 13:28:41 +00:00
return * this ;
}
2010-01-25 15:54:38 +00:00
const char * DirectoryIterator : : operator * ( ) const
{
if ( iter = = p - > files . end ( ) )
return NULL ;
return iter - > c_str ( ) ;
}
DirectoryIterator DirectoryIterator : : operator + + ( int )
{
DirectoryIterator tmp ( * this ) ;
+ + * this ;
return tmp ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
int ForEachFile ( const char * szDirName , bool ( * fnCallback ) ( const char * ) )
{
2009-05-08 13:28:41 +00:00
if ( ! szDirName | | ! fnCallback )
return 0 ;
char szFilename [ _MAX_PATH + 1 ] ;
SCopy ( szDirName , szFilename ) ;
bool fHasWildcard = ( SCharPos ( ' * ' , szFilename ) > = 0 ) ;
if ( ! fHasWildcard ) // parameter without wildcard: Append "/*.*" or "\*.*"
AppendBackslash ( szFilename ) ;
int iFileCount = 0 ;
# ifdef _WIN32
struct _finddata_t fdt ; int fdthnd ;
if ( ! fHasWildcard ) // parameter without wildcard: Append "/*.*" or "\*.*"
SAppend ( " * " , szFilename , _MAX_PATH ) ;
if ( ( fdthnd = _findfirst ( ( char * ) szFilename , & fdt ) ) < 0 )
return 0 ;
2010-03-28 18:58:01 +00:00
do
{
2009-05-08 13:28:41 +00:00
if ( SEqual ( fdt . name , " . " ) | | SEqual ( fdt . name , " .. " ) ) continue ;
SCopy ( fdt . name , GetFilename ( szFilename ) ) ;
if ( ( * fnCallback ) ( szFilename ) )
iFileCount + + ;
2010-03-28 18:58:01 +00:00
}
while ( _findnext ( fdthnd , & fdt ) = = 0 ) ;
2009-05-08 13:28:41 +00:00
_findclose ( fdthnd ) ;
# else
2009-05-11 17:47:28 +00:00
if ( fHasWildcard ) fprintf ( stderr , " Warning: ForEachFile with * (%s) \n " , szDirName ) ;
2009-05-08 13:28:41 +00:00
DIR * d = opendir ( szDirName ) ;
2009-05-08 19:06:50 +00:00
if ( ! d ) return 0 ;
2009-05-08 13:28:41 +00:00
dirent * ent ;
2010-03-28 18:58:01 +00:00
while ( ( ent = readdir ( d ) ) )
{
2009-05-08 13:28:41 +00:00
SCopy ( ent - > d_name , GetFilename ( szFilename ) ) ;
if ( ( * fnCallback ) ( szFilename ) )
iFileCount + + ;
}
closedir ( d ) ;
# endif
return iFileCount ;
}