DragonNest/Common/ZipArchive/DirEnumerator.cpp
2024-12-19 09:48:26 +08:00

186 lines
4.2 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// This source file is part of the ZipArchive library source distribution and
// is Copyrighted 2000 - 2012 by Artpol Software - Tadeusz Dracz
//
// 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
// of the License, or (at your option) any later version.
//
// For the licensing details refer to the License.txt file.
//
// Web Site: http://www.artpol-software.com
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#if defined _MSC_VER && _MSC_VER < 1300
// STL warnings
#pragma warning (push, 3)
#endif
#include "DirEnumerator.h"
#include "FileFilter.h"
#include <queue>
#if defined __GNUC__ && !defined __MINGW32__
#include <sys/stat.h>
#include <dirent.h>
#else
#include <io.h>
#ifdef __BORLANDC__
#ifndef _tfindfirsti64
#define _tfindfirsti64 __tfindfirsti64
#endif
#ifndef _tfindnexti64
#define _tfindnexti64 __tfindnexti64
#endif
#ifndef _tfinddatai64_t
#define _tfinddatai64_t __tfinddatai64_t
#endif
#endif
#endif
namespace ZipArchiveLib
{
#if defined __GNUC__ && !defined __MINGW32__
#define ZIP_ENUMERATOR_FOR_GNUC
#endif
bool CDirEnumerator::Start(CFileFilter& filter)
{
OnEnumerationBegin();
std::queue<CZipString> dirs;
dirs.push(CZipString(m_lpszDirectory));
bool ret = true;
do
{
m_szCurrentDirectory = dirs.front();
dirs.pop();
CZipPathComponent::AppendSeparator(m_szCurrentDirectory);
EnterDirectory();
#ifdef ZIP_ENUMERATOR_FOR_GNUC
DIR* dp = opendir(m_szCurrentDirectory);
if (dp)
{
while (true)
{
struct dirent* entry = readdir(dp);
if (!entry)
break;
CZipString path(m_szCurrentDirectory + entry->d_name);
#if !defined __APPLE__ && !defined __CYGWIN__
struct stat64 sStats;
if (stat64(path, &sStats) == -1)
#else
struct stat sStats;
if (stat(path, &sStats) == -1)
#endif
continue;
LPCTSTR name = entry->d_name;
CFileInfo info;
info.m_uAttributes = sStats.st_mode;
#else
CZipString szFullFileName = m_szCurrentDirectory + _T("*");
_tfinddatai64_t ffInfo;
#if _MSC_VER > 1200
intptr_t hFile;
#else
long hFile;
#endif
if( (hFile = _tfindfirsti64( (LPTSTR)(LPCTSTR)szFullFileName, &ffInfo )) != -1L )
{
do
{
LPCTSTR name = ffInfo.name;
CFileInfo info;
info.m_uAttributes = ffInfo.attrib;
#endif
bool isDir;
if (ZipPlatform::IsDirectory(info.m_uAttributes))
{
if (!m_bRecursive || IsDots(name))
continue;
isDir = true;
}
else
isDir = false;
#ifdef ZIP_ENUMERATOR_FOR_GNUC
info.m_uSize = (ZIP_FILE_USIZE)sStats.st_size;
info.m_uCreateTime = sStats.st_ctime;
info.m_uModTime = sStats.st_mtime;
info.m_uAccessTime = sStats.st_atime;
#else
info.m_uSize = (ZIP_FILE_USIZE)ffInfo.size;
info.m_uCreateTime = ffInfo.time_create;
info.m_uModTime = ffInfo.time_write;
info.m_uAccessTime = ffInfo.time_access;
CZipString path(m_szCurrentDirectory + ffInfo.name);
#endif
if (isDir)
{
bool bAllow;
if (filter.HandlesFile(info))
bAllow = filter.Evaluate(path, name, info) && Process(path, info);
else
// examine directory, if the filter cannot decide
bAllow = true;
if (bAllow)
dirs.push(path);
}
else
{
bool bAllow;
if (filter.HandlesFile(info))
bAllow = filter.Evaluate(path, name, info);
else
// skip file, if the filter cannot decide
bAllow = false;
if (bAllow && !Process(path, info))
{
ret = false;
break;
}
}
#ifdef ZIP_ENUMERATOR_FOR_GNUC
}
closedir(dp);
}
#else
}
while (_tfindnexti64(hFile, &ffInfo) == 0L);
_findclose(hFile);
}
#endif
ExitDirectory();
}
while(!dirs.empty() && ret);
OnEnumerationEnd(ret);
return ret;
}
bool CDirEnumerator::IsDots(LPCTSTR lpszName)
{
CZipString name(lpszName);
return name.Compare(_T(".")) == 0 || name.Compare(_T("..")) == 0;
}
} // namespace
#if defined _MSC_VER && _MSC_VER < 1300
// STL warnings
#pragma warning (pop)
#endif