/*
* Copyright (C) 2012 Yee Young Han (http://blog.naver.com/websearch)
*
* 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 3 of the License, 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include
#include "Directory.h"
#include "Log.h"
#ifndef WIN32
#include
#include
#include
#include
#endif
#include "MemoryDebug.h"
/**
* @ingroup SipPlatform
* @brief µð·ºÅ丮¸¦ »ý¼ºÇÑ´Ù.
*
* ÀÌ¹Ì µð·ºÅ丮°¡ »ý¼ºµÇ¾î ÀÖÀ¸¸é ¾Æ¹«·± µ¿ÀÛÀ» ÇÏÁö ¾Ê´Â´Ù.
* "c:\temp\test" ¿Í °°Àº ¹®ÀÚ¿À» ÀÔ·ÂÇÏ¸é ´ÙÀ½°ú °°ÀÌ µ¿ÀÛÇÏ´Ù.
* "c:\temp" µð·ºÅ丮°¡ Á¸ÀçÇÏÁö ¾ÊÀ¸¸é À̸¦ »ý¼ºÇÑ ÈÄ, "c:\temp\test" µð·ºÅ丮¸¦ »ý¼ºÇÑ´Ù.
*
* @param szDirName [in] »ý¼ºÇÒ µð·ºÅ丮ÀÇ full pathname
* @param iDirMode [in] »ý¼ºÇÒ µð·ºÅ丮ÀÇ ±ÇÇÑ
* @return ¼º°øÇϸé true À» ¸®ÅÏÇÏ°í ½ÇÆÐÇϸé false ¸¦ ¸®ÅÏÇÑ´Ù.
*/
bool CDirectory::Create( const char * szDirName, int iDirMode )
{
int i, iLen, iCount, n;
char * pszName;
char fisNotDirectory = 0; // µð·ºÅ丮°¡ ¾Æ´Ñ°¡?
char fisError = 0; // µð·ºÅ丮 »ý¼º½Ã¿¡ ¿¡·¯°¡ ¹ß»ýÇÏ¿´´Â°¡?
iLen = (int)strlen( szDirName );
pszName = new char[ iLen + 1 ];
memset( pszName, 0, iLen + 1 );
for( i = 0, iCount = 0; i < iLen; i++ )
{
if( szDirName[i] == DIR_SEP )
{
iCount++;
// µð·ºÅ丮 À̸§ÀÌ "c:\test\temp\" ¶Ç´Â "/test/temp/" À̹ǷΠµÎ¹øÂ° µð·ºÅ丮
// ±¸ºÐÀÚ ºÎÅÍ µð·ºÅ丮¸¦ »ý¼ºÇÏ¸é µÈ´Ù.
if( iCount >= 2 )
{
n = CDirectory::IsDirectoryCheck( pszName );
if( n == -1 )
{
// µð·ºÅ丮°¡ ¾Æ´Ñ °æ¿ì
fisNotDirectory = 1;
break;
}
else if( n == -2 )
{
// µð·ºÅ丮°¡ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì
#ifdef WIN32
if( CreateDirectory( pszName, NULL ) == FALSE )
#else
if( mkdir( pszName, iDirMode ) != 0 )
#endif
{
fisError = 1;
break;
}
}
}
}
pszName[i] = szDirName[i];
}
delete [] pszName;
if( fisNotDirectory == 1 ) return false;
if( fisError == 1 ) return false;
// µð·ºÅ丮 À̸§ÀÌ "c:\test\temp" ¶Ç´Â "/test/temp" ÀÏ °æ¿ì, À§ÀÇ loop ¿¡¼ temp µð·ºÅ丮¸¦
// »ý¼ºÇÏÁö ¾ÊÀ¸¹Ç·Î À̸¦ »ý¼ºÇϱâ À§Çؼ ¾Æ·¡ÀÇ Äڵ尡 ÇÊ¿äÇÏ´Ù.
if( szDirName[iLen-1] != DIR_SEP )
{
n = CDirectory::IsDirectoryCheck( szDirName );
if( n == -1 )
{
// µð·ºÅ丮°¡ ¾Æ´Ñ °æ¿ì
return false;
}
else if( n == -2 )
{
// µð·ºÅ丮°¡ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì
#ifdef WIN32
if( CreateDirectory( szDirName, NULL ) == FALSE )
#else
if( mkdir( szDirName, iDirMode ) != 0 )
#endif
{
return false;
}
}
}
return true;
}
/**
* @ingroup SipPlatform
* @brief »ç¿ëÀÚ°¡ ÀÔ·ÂÇÑ path °¡ µð·ºÅ丮ÀÎÁö¸¦ Á¡°ËÇÑ´Ù.
* @param szDirName [in] µð·ºÅ丮 À̸§
* @return ÀÔ·ÂµÈ path °¡ µð·ºÅ丮À̸é true ¸¦ ¸®ÅÏÇÏ°í ±×·¸Áö ¾ÊÀ¸¸é false ¸¦ ¸®ÅÏÇÑ´Ù.
*/
bool CDirectory::IsDirectory( const char * szDirName )
{
if( CDirectory::IsDirectoryCheck( szDirName ) == 0 ) return true;
return false;
}
/**
* @ingroup SipPlatform
* @brief »ç¿ëÀÚ°¡ ÀÔ·ÂÇÑ path °¡ µð·ºÅ丮ÀÎÁö¸¦ Á¡°ËÇÑ´Ù.
* @param szDirName [in] µð·ºÅ丮 À̸§
* @return ÀÔ·ÂµÈ path °¡ µð·ºÅ丮À̸é 0 À» ¸®ÅÏÇÑ´Ù.
* Á¸ÀçÇÏÁö ¾ÊÀ¸¸é -2 À» ¸®ÅÏÇÑ´Ù.
* µð·ºÅ丮°¡ ¾Æ´Ï¸é -1 À» ¸®ÅÏÇÑ´Ù.
*/
int CDirectory::IsDirectoryCheck( const char * szDirName )
{
#ifdef WIN32
// ACE ¿¡¼ S_ISDIR À» Áö¿øÇÏÁö ¾Ê±â ¶§¹®¿¡ À©µµ¿ìÀÇ °æ¿ì¸¦ À§ÇÏ¿© WINAPI ¸¦ »ç¿ëÇÏ¿´À½.
DWORD iAttribute = GetFileAttributes( szDirName );
if( iAttribute != -1 )
{
if( iAttribute & FILE_ATTRIBUTE_DIRECTORY )
{
return 0;
}
else
{
return -1;
}
}
else
{
// ÆÄÀÏÀÌ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì.
return -2;
}
#else
struct stat clsStat;
if( stat( szDirName, &clsStat ) == 0 )
{
if( S_ISDIR( clsStat.st_mode ) )
{
return 0;
}
else
{
return -1;
}
}
else
{
// ÆÄÀÏÀÌ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì.
return -2;
}
#endif
return 0;
}
/**
* @ingroup SipPlatform
* @brief ÆÄÀÏ °æ·Î¿¡ ÆÄÀÏ À̸§À» Ãß°¡ÇÑ´Ù.
* @param strFileName ÆÄÀÏ °æ·Î
* @param pszAppend Ãß°¡ÇÒ ÆÄÀÏ À̸§
*/
void CDirectory::AppendName( std::string & strFileName, const char * pszAppend )
{
#ifdef WIN32
strFileName.append( "\\" );
strFileName.append( pszAppend );
#else
strFileName.append( "/" );
strFileName.append( pszAppend );
#endif
}
/**
* @ingroup SipPlatform
* @brief Æú´õ¿¡ Á¸ÀçÇÏ´Â ¸ðµç ÆÄÀÏ/Æú´õ ¸®½ºÆ®¸¦ °¡Á®¿Â´Ù.
* @param pszDirName Æú´õ °æ·Î
* @param clsFileList ÆÄÀÏ/Æú´õ ¸®½ºÆ®¸¦ ÀúÀåÇÒ º¯¼ö
* @returns ¼º°øÇϸé true ¸¦ ¸®ÅÏÇÏ°í ½ÇÆÐÇϸé false ¸¦ ¸®ÅÏÇÑ´Ù.
*/
bool CDirectory::List( const char * pszDirName, FILE_LIST & clsFileList )
{
clsFileList.clear();
#ifdef WIN32
WIN32_FIND_DATA sttFindData;
HANDLE hFind;
BOOL bNext = TRUE;
std::string strPath = pszDirName;
strPath.append( "\\*.*" );
hFind = FindFirstFile( strPath.c_str(), &sttFindData );
if( hFind == INVALID_HANDLE_VALUE )
{
CLog::Print( LOG_ERROR, "FindFirstFile(%s) error(%d)", pszDirName, GetLastError() );
return false;
}
for( ; bNext == TRUE; bNext = FindNextFile( hFind, &sttFindData ) )
{
if( !strcmp( sttFindData.cFileName, "." ) || !strcmp( sttFindData.cFileName, ".." ) ) continue;
clsFileList.push_back( sttFindData.cFileName );
}
FindClose( hFind );
#else
DIR * psttDir;
struct dirent * psttDirent, sttDirent;
int n;
psttDir = opendir( pszDirName );
if( psttDir == NULL )
{
CLog::Print( LOG_ERROR, "opendir(%s) error(%d)", pszDirName, errno );
return false;
}
for( n = readdir_r( psttDir, &sttDirent, &psttDirent ); psttDirent && n == 0; n = readdir_r( psttDir, &sttDirent, &psttDirent ) )
{
if( !strcmp( psttDirent->d_name, "." ) || !strcmp( psttDirent->d_name, ".." ) ) continue;
clsFileList.push_back( psttDirent->d_name );
}
closedir( psttDir );
#endif
return true;
}
/**
* @ingroup SipPlatform
* @brief Æú´õ¿¡ Á¸ÀçÇÏ´Â ¸ðµç ÆÄÀÏ ¸®½ºÆ®¸¦ °¡Á®¿Â´Ù.
* @param pszDirName Æú´õ °æ·Î
* @param clsFileList ÆÄÀÏ ¸®½ºÆ®¸¦ ÀúÀåÇÒ º¯¼ö
* @returns ¼º°øÇϸé true ¸¦ ¸®ÅÏÇÏ°í ½ÇÆÐÇϸé false ¸¦ ¸®ÅÏÇÑ´Ù.
*/
bool CDirectory::FileList( const char * pszDirName, FILE_LIST & clsFileList )
{
clsFileList.clear();
#ifdef WIN32
WIN32_FIND_DATA sttFindData;
HANDLE hFind;
BOOL bNext = TRUE;
std::string strPath = pszDirName;
strPath.append( "\\*.*" );
hFind = FindFirstFile( strPath.c_str(), &sttFindData );
if( hFind == INVALID_HANDLE_VALUE )
{
CLog::Print( LOG_ERROR, "FindFirstFile(%s) error(%d)", pszDirName, GetLastError() );
return false;
}
for( ; bNext == TRUE; bNext = FindNextFile( hFind, &sttFindData ) )
{
if( !strcmp( sttFindData.cFileName, "." ) || !strcmp( sttFindData.cFileName, ".." ) ) continue;
if( sttFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) continue;
clsFileList.push_back( sttFindData.cFileName );
}
FindClose( hFind );
#else
DIR * psttDir;
struct dirent * psttDirent, sttDirent;
struct stat sttStat;
int n;
std::string strFileName;
psttDir = opendir( pszDirName );
if( psttDir == NULL )
{
CLog::Print( LOG_ERROR, "opendir(%s) error(%d)", pszDirName, errno );
return false;
}
for( n = readdir_r( psttDir, &sttDirent, &psttDirent ); psttDirent && n == 0; n = readdir_r( psttDir, &sttDirent, &psttDirent ) )
{
if( !strcmp( psttDirent->d_name, "." ) || !strcmp( psttDirent->d_name, ".." ) ) continue;
strFileName = pszDirName;
AppendName( strFileName, psttDirent->d_name );
if( lstat( strFileName.c_str(), &sttStat ) < 0 ) continue;
if( S_ISDIR( sttStat.st_mode ) ) continue;
clsFileList.push_back( psttDirent->d_name );
}
closedir( psttDir );
#endif
return true;
}
/**
* @ingroup SipPlatform
* @brief ÇÁ·Î±×·¥À» ½ÃÀÛÇÑ Æú´õ¸¦ °¡Á®¿Â´Ù.
* @returns ÇÁ·Î±×·¥À» ½ÃÀÛÇÑ Æú´õ °æ·Î¸¦ ¸®ÅÏÇÑ´Ù.
*/
char * CDirectory::GetProgramDirectory( )
{
static char szDir[1024];
if( strlen(szDir) == 0 )
{
#ifdef WIN32
int i;
HMODULE hThis;
hThis = GetModuleHandle( NULL );
GetModuleFileName( hThis, szDir, sizeof(szDir));
for( i = (int)strlen( szDir) - 1; i >= 0; i-- )
{
if( szDir[i] == '\\' )
{
szDir[i] = '\0';
break;
}
}
#else
if( readlink( "/proc/self/exe", szDir, sizeof(szDir) ) != -1 )
{
for( int i = (int)strlen( szDir) - 1; i >= 0; i-- )
{
if( szDir[i] == '/' )
{
szDir[i] = '\0';
break;
}
}
}
#endif
}
return szDir;
}
#define MAX_INT 4294967296L
/**
* @ingroup SipPlatform
* @brief Æú´õ Å©±â¸¦ °¡Á®¿Â´Ù.
* @param pszDirName Æú´õ fulll path
* @returns Æú´õ Å©±â¸¦ ¸®ÅÏÇÑ´Ù.
*/
int64_t CDirectory::GetSize( const char * pszDirName )
{
uint64_t iTotalSize = 0;
#ifdef WIN32
WIN32_FIND_DATA sttFindData;
HANDLE hFind;
BOOL bNext = TRUE;
std::string strPath = pszDirName;
strPath.append( "\\*.*" );
hFind = FindFirstFile( strPath.c_str(), &sttFindData );
if( hFind == INVALID_HANDLE_VALUE )
{
CLog::Print( LOG_ERROR, "FindFirstFile(%s) error(%d)", pszDirName, GetLastError() );
return false;
}
for( ; bNext == TRUE; bNext = FindNextFile( hFind, &sttFindData ) )
{
if( !strcmp( sttFindData.cFileName, "." ) || !strcmp( sttFindData.cFileName, ".." ) ) continue;
if( sttFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
std::string strFolder = pszDirName;
AppendName( strFolder, sttFindData.cFileName );
iTotalSize += GetSize( strFolder.c_str() );
continue;
}
if( sttFindData.nFileSizeHigh > 0 )
{
iTotalSize += (uint64_t)sttFindData.nFileSizeHigh * MAX_INT;
}
iTotalSize += sttFindData.nFileSizeLow;
}
FindClose( hFind );
#else
DIR * psttDir;
struct dirent * psttDirent, sttDirent;
struct stat sttStat;
int n;
std::string strFileName;
psttDir = opendir( pszDirName );
if( psttDir == NULL )
{
CLog::Print( LOG_ERROR, "opendir(%s) error(%d)", pszDirName, errno );
return false;
}
for( n = readdir_r( psttDir, &sttDirent, &psttDirent ); psttDirent && n == 0; n = readdir_r( psttDir, &sttDirent, &psttDirent ) )
{
if( !strcmp( psttDirent->d_name, "." ) || !strcmp( psttDirent->d_name, ".." ) ) continue;
strFileName = pszDirName;
AppendName( strFileName, psttDirent->d_name );
if( lstat( strFileName.c_str(), &sttStat ) < 0 ) continue;
if( S_ISDIR( sttStat.st_mode ) )
{
std::string strFolder = pszDirName;
AppendName( strFolder, psttDirent->d_name );
iTotalSize += GetSize( strFolder.c_str() );
continue;
}
iTotalSize += sttStat.st_size;
}
closedir( psttDir );
#endif
return iTotalSize;
}
/**
* @ingroup SipPlatform
* @brief Æú´õ¿¡ Æ÷ÇÔµÈ ÆÄÀϵéÀ» ¸ðµÎ »èÁ¦ÇÑ´Ù.
* @param pszDirName Æú´õ full path
*/
void CDirectory::DeleteAllFile( const char * pszDirName )
{
FILE_LIST::iterator itFile;
FILE_LIST clsFileList;
FileList( pszDirName, clsFileList );
for( itFile = clsFileList.begin(); itFile != clsFileList.end(); ++itFile )
{
std::string strFileName = pszDirName;
CDirectory::AppendName( strFileName, itFile->c_str() );
#ifdef WIN32
DeleteFile( strFileName.c_str() );
#else
unlink( strFileName.c_str() );
#endif
}
}
/**
* @ingroup SipPlatform
* @brief ÆÄÀÏ °æ·Î¿¡¼ Æú´õ À̸§À» °¡Á®¿Â´Ù.
* @param pszFilePath ÆÄÀÏ °æ·Î
* @param strDirName Æú´õ À̸§À» ÀúÀåÇÒ º¯¼ö
*/
void CDirectory::GetDirName( const char * pszFilePath, std::string & strDirName )
{
int iLen = (int)strlen( pszFilePath );
strDirName.clear();
for( int i = iLen - 1; i >= 0; --i )
{
#ifdef WIN32
if( pszFilePath[i] == '\\' )
#else
if( pszFilePath[i] == '/' )
#endif
{
strDirName.append( pszFilePath, i );
break;
}
}
}
/**
* @ingroup SipPlatform
* @brief ÆÄÀÏ °æ·Î¿¡¼ ÆÄÀÏ À̸§À» °¡Á®¿Â´Ù.
* @param pszFilePath ÆÄÀÏ °æ·Î
* @param strFileName ÆÄÀÏ À̸§À» ÀúÀåÇÒ º¯¼ö
*/
void CDirectory::GetFileName( const char * pszFilePath, std::string & strFileName )
{
int iLen = (int)strlen( pszFilePath );
strFileName.clear();
for( int i = iLen - 1; i >= 0; --i )
{
#ifdef WIN32
if( pszFilePath[i] == '\\' )
#else
if( pszFilePath[i] == '/' )
#endif
{
strFileName = pszFilePath + i + 1;
break;
}
}
}
/**
* @ingroup SipPlatform
* @brief Æú´õ¸¦ ¸ðµÎ »èÁ¦ÇÑ´Ù.
* @param pszDirName Æú´õ À̸§
* @returns ¼º°øÇϸé true ¸¦ ¸®ÅÏÇÏ°í ½ÇÆÐÇϸé false ¸¦ ¸®ÅÏÇÑ´Ù.
*/
bool CDirectory::Delete( const char * pszDirName )
{
#ifdef WIN32
WIN32_FIND_DATA sttFindData;
HANDLE hFind;
BOOL bNext = TRUE;
std::string strPath = pszDirName;
std::string strFileName;
strPath.append( "\\*.*" );
hFind = FindFirstFile( strPath.c_str(), &sttFindData );
if( hFind == INVALID_HANDLE_VALUE )
{
CLog::Print( LOG_ERROR, "FindFirstFile(%s) error(%d)", pszDirName, GetLastError() );
return false;
}
for( ; bNext == TRUE; bNext = FindNextFile( hFind, &sttFindData ) )
{
if( !strcmp( sttFindData.cFileName, "." ) || !strcmp( sttFindData.cFileName, ".." ) ) continue;
strFileName = pszDirName;
CDirectory::AppendName( strFileName, sttFindData.cFileName );
if( sttFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
CDirectory::Delete( strFileName.c_str() );
RemoveDirectory( strFileName.c_str() );
}
else
{
DeleteFile( strFileName.c_str() );
}
}
FindClose( hFind );
RemoveDirectory( pszDirName );
#else
DIR * psttDir;
struct dirent * psttDirent, sttDirent;
struct stat sttStat;
int n;
std::string strFileName;
psttDir = opendir( pszDirName );
if( psttDir == NULL )
{
CLog::Print( LOG_ERROR, "opendir(%s) error(%d)", pszDirName, errno );
return false;
}
for( n = readdir_r( psttDir, &sttDirent, &psttDirent ); psttDirent && n == 0; n = readdir_r( psttDir, &sttDirent, &psttDirent ) )
{
if( !strcmp( psttDirent->d_name, "." ) || !strcmp( psttDirent->d_name, ".." ) ) continue;
strFileName = pszDirName;
AppendName( strFileName, psttDirent->d_name );
if( lstat( strFileName.c_str(), &sttStat ) < 0 ) continue;
if( S_ISDIR( sttStat.st_mode ) )
{
CDirectory::Delete( strFileName.c_str() );
rmdir( strFileName.c_str() );
}
else
{
unlink( strFileName.c_str() );
}
}
closedir( psttDir );
rmdir( pszDirName );
#endif
return true;
}