FileSystem: Add error reporting to DeleteDirectory()
This commit is contained in:
parent
5c3abb490d
commit
0e6ade067c
|
@ -1611,27 +1611,32 @@ bool FileSystem::EnsureDirectoryExists(const char* path, bool recursive, Error*
|
|||
return FileSystem::CreateDirectory(path, recursive, error);
|
||||
}
|
||||
|
||||
bool FileSystem::RecursiveDeleteDirectory(const char* path)
|
||||
bool FileSystem::RecursiveDeleteDirectory(const char* path, Error* error)
|
||||
{
|
||||
FindResultsArray results;
|
||||
if (FindFiles(path, "*", FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_FOLDERS | FILESYSTEM_FIND_HIDDEN_FILES, &results))
|
||||
{
|
||||
for (const FILESYSTEM_FIND_DATA& fd : results)
|
||||
{
|
||||
if (fd.Attributes & FILESYSTEM_FILE_ATTRIBUTE_DIRECTORY)
|
||||
// don't recurse into symlinked directories, just remove the link itself
|
||||
if ((fd.Attributes & (FILESYSTEM_FILE_ATTRIBUTE_DIRECTORY | FILESYSTEM_FILE_ATTRIBUTE_LINK)) ==
|
||||
FILESYSTEM_FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
if (!RecursiveDeleteDirectory(fd.FileName.c_str()))
|
||||
if (!RecursiveDeleteDirectory(fd.FileName.c_str(), error))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!DeleteFile(fd.FileName.c_str()))
|
||||
if (!DeleteFile(fd.FileName.c_str(), error))
|
||||
{
|
||||
Error::AddPrefixFmt(error, "Failed to delete {}: ", fd.FileName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DeleteDirectory(path);
|
||||
return DeleteDirectory(path, error);
|
||||
}
|
||||
|
||||
bool FileSystem::CopyFilePath(const char* source, const char* destination, bool replace)
|
||||
|
@ -2156,17 +2161,32 @@ bool FileSystem::CreateDirectory(const char* Path, bool Recursive, Error* error)
|
|||
bool FileSystem::DeleteFile(const char* path, Error* error)
|
||||
{
|
||||
const std::wstring wpath = GetWin32Path(path);
|
||||
|
||||
// Need to handle both links/junctions and files as per unix.
|
||||
const DWORD fileAttributes = GetFileAttributesW(wpath.c_str());
|
||||
if (fileAttributes == INVALID_FILE_ATTRIBUTES || fileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
if (fileAttributes == INVALID_FILE_ATTRIBUTES ||
|
||||
((fileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) == FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
Error::SetStringView(error, "File does not exist.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DeleteFileW(wpath.c_str()))
|
||||
// if it's a junction/symlink, we need to use RemoveDirectory() instead
|
||||
if (fileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
Error::SetWin32(error, "DeleteFileW() failed: ", GetLastError());
|
||||
return false;
|
||||
if (!RemoveDirectoryW(wpath.c_str()))
|
||||
{
|
||||
Error::SetWin32(error, "RemoveDirectoryW() failed: ", GetLastError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!DeleteFileW(wpath.c_str()))
|
||||
{
|
||||
Error::SetWin32(error, "DeleteFileW() failed: ", GetLastError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2186,10 +2206,23 @@ bool FileSystem::RenamePath(const char* old_path, const char* new_path, Error* e
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FileSystem::DeleteDirectory(const char* path)
|
||||
bool FileSystem::DeleteDirectory(const char* path, Error* error)
|
||||
{
|
||||
const std::wstring wpath = GetWin32Path(path);
|
||||
return RemoveDirectoryW(wpath.c_str());
|
||||
const DWORD fileAttributes = GetFileAttributesW(wpath.c_str());
|
||||
if (fileAttributes == INVALID_FILE_ATTRIBUTES || !(fileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
Error::SetStringView(error, "File does not exist.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!RemoveDirectoryW(wpath.c_str()))
|
||||
{
|
||||
Error::SetWin32(error, "RemoveDirectoryW() failed: ", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string FileSystem::GetProgramPath()
|
||||
|
@ -2273,10 +2306,10 @@ bool FileSystem::SetPathCompression(const char* path, bool enable)
|
|||
|
||||
#elif !defined(__ANDROID__)
|
||||
|
||||
static u32 TranslateStatAttributes(struct stat& st)
|
||||
static u32 TranslateStatAttributes(struct stat& st, struct stat& st_link)
|
||||
{
|
||||
return (S_ISDIR(st.st_mode) ? FILESYSTEM_FILE_ATTRIBUTE_DIRECTORY : 0) |
|
||||
(S_ISLNK(st.st_mode) ? FILESYSTEM_FILE_ATTRIBUTE_LINK : 0);
|
||||
(S_ISLNK(st_link.st_mode) ? FILESYSTEM_FILE_ATTRIBUTE_LINK : 0);
|
||||
}
|
||||
|
||||
static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, const char* Path, const char* Pattern,
|
||||
|
@ -2330,12 +2363,12 @@ static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, co
|
|||
else
|
||||
full_path = fmt::format("{}/{}", OriginPath, pDirEnt->d_name);
|
||||
|
||||
struct stat sDir;
|
||||
if (stat(full_path.c_str(), &sDir) < 0)
|
||||
struct stat sDir, sDirLink;
|
||||
if (stat(full_path.c_str(), &sDir) < 0 || lstat(full_path.c_str(), &sDirLink) < 0)
|
||||
continue;
|
||||
|
||||
FILESYSTEM_FIND_DATA outData;
|
||||
outData.Attributes = TranslateStatAttributes(sDir);
|
||||
outData.Attributes = TranslateStatAttributes(sDir, sDirLink);
|
||||
|
||||
if (S_ISDIR(sDir.st_mode))
|
||||
{
|
||||
|
@ -2478,18 +2511,18 @@ bool FileSystem::StatFile(std::FILE* fp, struct stat* st, Error* error)
|
|||
bool FileSystem::StatFile(const char* path, FILESYSTEM_STAT_DATA* sd, Error* error)
|
||||
{
|
||||
// stat file
|
||||
struct stat sysStatData;
|
||||
if (stat(path, &sysStatData) < 0)
|
||||
struct stat ssd, ssd_link;
|
||||
if (stat(path, &ssd) < 0 || lstat(path, &ssd_link) < 0)
|
||||
{
|
||||
Error::SetErrno(error, "stat() failed: ", errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse attributes
|
||||
sd->CreationTime = sysStatData.st_ctime;
|
||||
sd->ModificationTime = sysStatData.st_mtime;
|
||||
sd->Attributes = TranslateStatAttributes(sysStatData);
|
||||
sd->Size = S_ISREG(sysStatData.st_mode) ? sysStatData.st_size : 0;
|
||||
sd->CreationTime = ssd.st_ctime;
|
||||
sd->ModificationTime = ssd.st_mtime;
|
||||
sd->Attributes = TranslateStatAttributes(ssd, ssd_link);
|
||||
sd->Size = S_ISREG(ssd.st_mode) ? ssd.st_size : 0;
|
||||
|
||||
// ok
|
||||
return true;
|
||||
|
@ -2505,18 +2538,18 @@ bool FileSystem::StatFile(std::FILE* fp, FILESYSTEM_STAT_DATA* sd, Error* error)
|
|||
}
|
||||
|
||||
// stat file
|
||||
struct stat sysStatData;
|
||||
if (fstat(fd, &sysStatData) != 0)
|
||||
struct stat ssd;
|
||||
if (fstat(fd, &ssd) != 0)
|
||||
{
|
||||
Error::SetErrno(error, "stat() failed: ", errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse attributes
|
||||
sd->CreationTime = sysStatData.st_ctime;
|
||||
sd->ModificationTime = sysStatData.st_mtime;
|
||||
sd->Attributes = TranslateStatAttributes(sysStatData);
|
||||
sd->Size = S_ISREG(sysStatData.st_mode) ? sysStatData.st_size : 0;
|
||||
sd->CreationTime = ssd.st_ctime;
|
||||
sd->ModificationTime = ssd.st_mtime;
|
||||
sd->Attributes = TranslateStatAttributes(ssd, ssd);
|
||||
sd->Size = S_ISREG(ssd.st_mode) ? ssd.st_size : 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2655,8 +2688,8 @@ bool FileSystem::CreateDirectory(const char* path, bool recursive, Error* error)
|
|||
|
||||
bool FileSystem::DeleteFile(const char* path, Error* error)
|
||||
{
|
||||
struct stat sysStatData;
|
||||
if (stat(path, &sysStatData) != 0 || S_ISDIR(sysStatData.st_mode))
|
||||
struct stat sd;
|
||||
if (lstat(path, &sd) != 0 || (S_ISDIR(sd.st_mode) && !S_ISLNK(sd.st_mode)))
|
||||
{
|
||||
Error::SetStringView(error, "File does not exist.");
|
||||
return false;
|
||||
|
@ -2675,21 +2708,38 @@ bool FileSystem::RenamePath(const char* old_path, const char* new_path, Error* e
|
|||
{
|
||||
if (rename(old_path, new_path) != 0)
|
||||
{
|
||||
const int err = errno;
|
||||
Error::SetErrno(error, "rename() failed: ", err);
|
||||
Error::SetErrno(error, "rename() failed: ", errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileSystem::DeleteDirectory(const char* path)
|
||||
bool FileSystem::DeleteDirectory(const char* path, Error* error)
|
||||
{
|
||||
struct stat sysStatData;
|
||||
if (stat(path, &sysStatData) != 0 || !S_ISDIR(sysStatData.st_mode))
|
||||
struct stat sd;
|
||||
if (stat(path, &sd) != 0 || !S_ISDIR(sd.st_mode))
|
||||
return false;
|
||||
|
||||
return (rmdir(path) == 0);
|
||||
// if it's a symlink, use unlink() instead
|
||||
if (S_ISLNK(sd.st_mode))
|
||||
{
|
||||
if (unlink(path) != 0)
|
||||
{
|
||||
Error::SetErrno(error, "unlink() failed: ", errno);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rmdir(path) != 0)
|
||||
{
|
||||
Error::SetErrno(error, "rmdir() failed: ", errno);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string FileSystem::GetProgramPath()
|
||||
|
|
|
@ -202,10 +202,10 @@ bool CreateDirectory(const char* path, bool recursive, Error* error = nullptr);
|
|||
bool EnsureDirectoryExists(const char* path, bool recursive, Error* error = nullptr);
|
||||
|
||||
/// Removes a directory.
|
||||
bool DeleteDirectory(const char* path);
|
||||
bool DeleteDirectory(const char* path, Error* error = nullptr);
|
||||
|
||||
/// Recursively removes a directory and all subdirectories/files.
|
||||
bool RecursiveDeleteDirectory(const char* path);
|
||||
bool RecursiveDeleteDirectory(const char* path, Error* error = nullptr);
|
||||
|
||||
/// Copies one file to another, optionally replacing it if it already exists.
|
||||
bool CopyFilePath(const char* source, const char* destination, bool replace);
|
||||
|
|
|
@ -133,22 +133,27 @@ bool Updater::RecursiveDeleteDirectory(const char* path, bool remove_dir)
|
|||
|
||||
return true;
|
||||
#else
|
||||
Error error;
|
||||
FileSystem::FindResultsArray results;
|
||||
if (FileSystem::FindFiles(path, "*", FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_FOLDERS | FILESYSTEM_FIND_HIDDEN_FILES,
|
||||
&results))
|
||||
{
|
||||
for (const FILESYSTEM_FIND_DATA& fd : results)
|
||||
{
|
||||
if (fd.Attributes & FILESYSTEM_FILE_ATTRIBUTE_DIRECTORY)
|
||||
if ((fd.Attributes & (FILESYSTEM_FILE_ATTRIBUTE_DIRECTORY | FILESYSTEM_FILE_ATTRIBUTE_LINK)) ==
|
||||
FILESYSTEM_FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
if (!RecursiveDeleteDirectory(fd.FileName.c_str(), true))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_progress->FormatInformation("Removing directory '{}'.", fd.FileName);
|
||||
if (!FileSystem::DeleteFile(fd.FileName.c_str()))
|
||||
m_progress->FormatInformation("Removing file '{}'.", fd.FileName);
|
||||
if (!FileSystem::DeleteFile(fd.FileName.c_str(), &error))
|
||||
{
|
||||
m_progress->FormatModalError("DeleteFile({}) failed: {}", fd.FileName, error.GetDescription());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +162,13 @@ bool Updater::RecursiveDeleteDirectory(const char* path, bool remove_dir)
|
|||
return true;
|
||||
|
||||
m_progress->FormatInformation("Removing directory '{}'.", path);
|
||||
return FileSystem::DeleteDirectory(path);
|
||||
if (!FileSystem::DeleteDirectory(path, &error))
|
||||
{
|
||||
m_progress->FormatModalError("DeleteDirectory({}) failed: {}", path, error.GetDescription());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue