You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
8.1 KiB
260 lines
8.1 KiB
//
|
|
// copied from fusion\util\io.cpp with minor changes
|
|
//
|
|
// xiaoyuw@ 09/05/2001
|
|
//
|
|
|
|
#include "stdinc.h"
|
|
#include "macros.h"
|
|
|
|
#include "fusionbuffer.h"
|
|
#include "fusionhandle.h"
|
|
|
|
#include "fuseio.h"
|
|
|
|
static BOOL
|
|
FusionpIsDotOrDotDot(
|
|
PCWSTR str
|
|
)
|
|
{
|
|
return ((str[0] == L'.') && ((str[1] == L'\0') || ((str[1] == L'.') && (str[2] == L'\0'))));
|
|
}
|
|
|
|
static BOOL
|
|
IsStarOrStarDotStar(
|
|
PCWSTR str
|
|
)
|
|
{
|
|
return (str[0] == '*'
|
|
&& (str[1] == 0 || (str[1] == '.' && str[2] == '*' && str[3] == 0)));
|
|
}
|
|
|
|
|
|
CDirWalk::ECallbackResult
|
|
CDirWalk::WalkHelper(
|
|
)
|
|
{
|
|
const PCWSTR* fileFilter = NULL;
|
|
BOOL fGotAll = FALSE;
|
|
BOOL fThisIsAll = FALSE;
|
|
CFindFile hFind;
|
|
SIZE_T directoryLength = m_strParent.Cch();
|
|
ECallbackResult result = eKeepWalking;
|
|
|
|
::ZeroMemory(&m_fileData, sizeof(m_fileData));
|
|
result |= m_callback(eBeginDirectory, this);
|
|
if (result & (eError | eSuccess))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if ((result & eStopWalkingFiles) == 0)
|
|
{
|
|
for (fileFilter = m_fileFiltersBegin ; fileFilter != m_fileFiltersEnd ; ++fileFilter)
|
|
{
|
|
//
|
|
// FindFirstFile equates *.* with *, so we do too.
|
|
//
|
|
fThisIsAll = ::IsStarOrStarDotStar(*fileFilter);
|
|
fGotAll = fGotAll || fThisIsAll;
|
|
if (!m_strParent.Win32EnsureTrailingPathSeparator())
|
|
goto Error;
|
|
if (!m_strParent.Win32Append(*fileFilter, (*fileFilter != NULL) ? ::wcslen(*fileFilter) : 0))
|
|
goto Error;
|
|
hFind = ::FindFirstFileW(m_strParent, &m_fileData);
|
|
m_strParent.Left(directoryLength);
|
|
if (hFind != INVALID_HANDLE_VALUE)
|
|
{
|
|
do
|
|
{
|
|
if (::FusionpIsDotOrDotDot(m_fileData.cFileName))
|
|
continue;
|
|
|
|
if (!m_strLastObjectFound.Win32Assign(m_fileData.cFileName, ::wcslen(m_fileData.cFileName)))
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// we recurse on directories only if we are getting all of them
|
|
// otherwise we do them afterward
|
|
//
|
|
// the order directories are visited is therefore inconsistent, but
|
|
// most applications should be happy enough with the eEndDirectory
|
|
// notification (to implement rd /q/s)
|
|
//
|
|
if (m_fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
if (fThisIsAll && (result & eStopWalkingDirectories) == 0)
|
|
{
|
|
if (!m_strParent.Win32Append("\\", 1))
|
|
{
|
|
goto Error;
|
|
}
|
|
if (!m_strParent.Win32Append(m_fileData.cFileName, ::wcslen(m_fileData.cFileName)))
|
|
{
|
|
goto Error;
|
|
}
|
|
result |= WalkHelper();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((result & eStopWalkingFiles) == 0)
|
|
{
|
|
result |= m_callback(eFile, this);
|
|
}
|
|
}
|
|
m_strParent.Left(directoryLength);
|
|
if (result & (eError | eSuccess))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (fThisIsAll)
|
|
{
|
|
if ((result & eStopWalkingDirectories) &&
|
|
(result & eStopWalkingFiles))
|
|
{
|
|
if (!hFind.Win32Close())
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
goto StopWalking;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (result & eStopWalkingFiles)
|
|
{
|
|
if (!hFind.Win32Close())
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
goto StopWalking;
|
|
}
|
|
}
|
|
} while(::FindNextFileW(hFind, &m_fileData));
|
|
if (::GetLastError() != ERROR_NO_MORE_FILES)
|
|
{
|
|
goto Error;
|
|
}
|
|
if (!hFind.Win32Close())
|
|
{
|
|
goto Error;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
StopWalking:;
|
|
//
|
|
// make another pass with * to get all directories, if we haven't already
|
|
//
|
|
if (!fGotAll && (result & eStopWalkingDirectories) == 0)
|
|
{
|
|
if (!m_strParent.Win32Append("\\*", 2))
|
|
{
|
|
goto Error;
|
|
}
|
|
hFind = ::FindFirstFileW(m_strParent, &m_fileData);
|
|
m_strParent.Left(directoryLength);
|
|
if (hFind != INVALID_HANDLE_VALUE)
|
|
{
|
|
do
|
|
{
|
|
if (::FusionpIsDotOrDotDot(m_fileData.cFileName))
|
|
continue;
|
|
|
|
if ((m_fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!m_strLastObjectFound.Win32Assign(m_fileData.cFileName, ::wcslen(m_fileData.cFileName)))
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
if (!m_strParent.Win32Append("\\", 1))
|
|
{
|
|
goto Error;
|
|
}
|
|
if (!m_strParent.Win32Append(m_fileData.cFileName, ::wcslen(m_fileData.cFileName)))
|
|
{
|
|
goto Error;
|
|
}
|
|
result |= WalkHelper();
|
|
m_strParent.Left(directoryLength);
|
|
|
|
if (result & (eError | eSuccess))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (result & eStopWalkingDirectories)
|
|
{
|
|
goto StopWalkingDirs;
|
|
}
|
|
} while(::FindNextFileW(hFind, &m_fileData));
|
|
if (::GetLastError() != ERROR_NO_MORE_FILES)
|
|
{
|
|
goto Error;
|
|
}
|
|
StopWalkingDirs:
|
|
if (!hFind.Win32Close())
|
|
{
|
|
goto Error;
|
|
}
|
|
}
|
|
}
|
|
::ZeroMemory(&m_fileData, sizeof(m_fileData));
|
|
result |= m_callback(eEndDirectory, this);
|
|
if (result & (eError | eSuccess))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
result = eKeepWalking;
|
|
Exit:
|
|
if ((result & eStopWalkingDeep) == 0)
|
|
{
|
|
result &= ~(eStopWalkingFiles | eStopWalkingDirectories);
|
|
}
|
|
if (result & eError)
|
|
{
|
|
result |= (eStopWalkingFiles | eStopWalkingDirectories | eStopWalkingDeep);
|
|
}
|
|
return result;
|
|
Error:
|
|
result |= eError;
|
|
goto Exit;
|
|
}
|
|
|
|
CDirWalk::CDirWalk()
|
|
{
|
|
const static PCWSTR defaultFileFilter[] = { L"*" };
|
|
|
|
m_fileFiltersBegin = defaultFileFilter;
|
|
m_fileFiltersEnd = defaultFileFilter + NUMBER_OF(defaultFileFilter);
|
|
}
|
|
|
|
BOOL
|
|
CDirWalk::Walk()
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
//
|
|
// Save off the original path length before we go twiddling m_strParent
|
|
//
|
|
m_cchOriginalPath = m_strParent.Cch();
|
|
|
|
ECallbackResult result = WalkHelper();
|
|
if (result & eError)
|
|
{
|
|
if (::GetLastError() == ERROR_SUCCESS) // forget to set lasterror ?
|
|
::SetLastError(ERROR_INSTALL_FAILURE);
|
|
goto Exit;
|
|
}
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
return fSuccess;
|
|
}
|