FileSystem: Add Error to CreateDirectory()/RenamePath()

This commit is contained in:
Stenzek 2024-04-01 20:52:57 +10:00 committed by Connor McLaughlin
parent b06da6607b
commit 81502e6c7d
2 changed files with 57 additions and 25 deletions

View File

@ -8,6 +8,7 @@
#include "Console.h" #include "Console.h"
#include "StringUtil.h" #include "StringUtil.h"
#include "Path.h" #include "Path.h"
#include <algorithm> #include <algorithm>
#include <cerrno> #include <cerrno>
#include <cstdlib> #include <cstdlib>
@ -1182,13 +1183,13 @@ bool FileSystem::WriteStringToFile(const char* filename, const std::string_view&
return true; return true;
} }
bool FileSystem::EnsureDirectoryExists(const char* path, bool recursive) bool FileSystem::EnsureDirectoryExists(const char* path, bool recursive, Error* error)
{ {
if (FileSystem::DirectoryExists(path)) if (FileSystem::DirectoryExists(path))
return true; return true;
// if it fails to create, we're not going to be able to use it anyway // if it fails to create, we're not going to be able to use it anyway
return FileSystem::CreateDirectoryPath(path, recursive); return FileSystem::CreateDirectoryPath(path, recursive, error);
} }
bool FileSystem::RecursiveDeleteDirectory(const char* path) bool FileSystem::RecursiveDeleteDirectory(const char* path)
@ -1633,33 +1634,39 @@ bool FileSystem::DirectoryIsEmpty(const char* path)
return true; return true;
} }
bool FileSystem::CreateDirectoryPath(const char* Path, bool Recursive) bool FileSystem::CreateDirectoryPath(const char* Path, bool Recursive, Error* error)
{ {
const std::wstring wpath = GetWin32Path(Path); const std::wstring wpath = GetWin32Path(Path);
// has a path // has a path
if (wpath.empty()) if (wpath.empty()) [[unlikely]]
{
Error::SetStringView(error, "Path is empty.");
return false; return false;
}
// try just flat-out, might work if there's no other segments that have to be made // try just flat-out, might work if there's no other segments that have to be made
if (CreateDirectoryW(wpath.c_str(), nullptr)) if (CreateDirectoryW(wpath.c_str(), nullptr))
return true; return true;
if (!Recursive)
return false;
// check error // check error
DWORD lastError = GetLastError(); DWORD lastError = GetLastError();
if (lastError == ERROR_ALREADY_EXISTS) if (lastError == ERROR_ALREADY_EXISTS)
{ {
// check the attributes // check the attributes
u32 Attributes = GetFileAttributesW(wpath.c_str()); const u32 Attributes = GetFileAttributesW(wpath.c_str());
if (Attributes != INVALID_FILE_ATTRIBUTES && Attributes & FILE_ATTRIBUTE_DIRECTORY) if (Attributes != INVALID_FILE_ATTRIBUTES && Attributes & FILE_ATTRIBUTE_DIRECTORY)
return true; return true;
else
return false;
} }
else if (lastError == ERROR_PATH_NOT_FOUND)
if (!Recursive)
{
Error::SetWin32(error, "CreateDirectoryW() failed: ", lastError);
return false;
}
// check error
if (lastError == ERROR_PATH_NOT_FOUND)
{ {
// part of the path does not exist, so we'll create the parent folders, then // part of the path does not exist, so we'll create the parent folders, then
// the full path again. // the full path again.
@ -1677,7 +1684,10 @@ bool FileSystem::CreateDirectoryPath(const char* Path, bool Recursive)
{ {
lastError = GetLastError(); lastError = GetLastError();
if (lastError != ERROR_ALREADY_EXISTS) // fine, continue to next path segment if (lastError != ERROR_ALREADY_EXISTS) // fine, continue to next path segment
{
Error::SetWin32(error, "CreateDirectoryW() failed: ", lastError);
return false; return false;
}
} }
// replace / with \. // replace / with \.
@ -1697,7 +1707,10 @@ bool FileSystem::CreateDirectoryPath(const char* Path, bool Recursive)
{ {
lastError = GetLastError(); lastError = GetLastError();
if (lastError != ERROR_ALREADY_EXISTS) if (lastError != ERROR_ALREADY_EXISTS)
{
Error::SetWin32(error, "CreateDirectoryW() failed: ", lastError);
return false; return false;
}
} }
} }
@ -1707,6 +1720,7 @@ bool FileSystem::CreateDirectoryPath(const char* Path, bool Recursive)
else else
{ {
// unhandled error // unhandled error
Error::SetWin32(error, "CreateDirectoryW() failed: ", lastError);
return false; return false;
} }
} }
@ -1724,14 +1738,16 @@ bool FileSystem::DeleteFilePath(const char* path)
return (DeleteFileW(wpath.c_str()) == TRUE); return (DeleteFileW(wpath.c_str()) == TRUE);
} }
bool FileSystem::RenamePath(const char* old_path, const char* new_path) bool FileSystem::RenamePath(const char* old_path, const char* new_path, Error* error)
{ {
const std::wstring old_wpath = GetWin32Path(old_path); const std::wstring old_wpath = GetWin32Path(old_path);
const std::wstring new_wpath = GetWin32Path(new_path); const std::wstring new_wpath = GetWin32Path(new_path);
if (!MoveFileExW(old_wpath.c_str(), new_wpath.c_str(), MOVEFILE_REPLACE_EXISTING)) if (!MoveFileExW(old_wpath.c_str(), new_wpath.c_str(), MOVEFILE_REPLACE_EXISTING))
{ {
Console.Error("MoveFileEx('%s', '%s') failed: %08X", old_path, new_path, GetLastError()); const DWORD err = GetLastError();
Error::SetWin32(error, "MoveFileExW() failed: ", err);
Console.Error("MoveFileEx('%s', '%s') failed: %08X", old_path, new_path, err);
return false; return false;
} }
@ -2119,7 +2135,7 @@ bool FileSystem::DirectoryIsEmpty(const char* path)
return true; return true;
} }
bool FileSystem::CreateDirectoryPath(const char* path, bool recursive) bool FileSystem::CreateDirectoryPath(const char* path, bool recursive, Error* error)
{ {
// has a path // has a path
const size_t pathLength = std::strlen(path); const size_t pathLength = std::strlen(path);
@ -2130,9 +2146,6 @@ bool FileSystem::CreateDirectoryPath(const char* path, bool recursive)
if (mkdir(path, 0777) == 0) if (mkdir(path, 0777) == 0)
return true; return true;
if (!recursive)
return false;
// check error // check error
int lastError = errno; int lastError = errno;
if (lastError == EEXIST) if (lastError == EEXIST)
@ -2141,10 +2154,15 @@ bool FileSystem::CreateDirectoryPath(const char* path, bool recursive)
struct stat sysStatData; struct stat sysStatData;
if (stat(path, &sysStatData) == 0 && S_ISDIR(sysStatData.st_mode)) if (stat(path, &sysStatData) == 0 && S_ISDIR(sysStatData.st_mode))
return true; return true;
else
return false;
} }
else if (lastError == ENOENT)
if (!recursive)
{
Error::SetErrno(error, "mkdir() failed: ", lastError);
return false;
}
if (lastError == ENOENT)
{ {
// part of the path does not exist, so we'll create the parent folders, then // part of the path does not exist, so we'll create the parent folders, then
// the full path again. // the full path again.
@ -2160,7 +2178,10 @@ bool FileSystem::CreateDirectoryPath(const char* path, bool recursive)
{ {
lastError = errno; lastError = errno;
if (lastError != EEXIST) // fine, continue to next path segment if (lastError != EEXIST) // fine, continue to next path segment
{
Error::SetErrno(error, "mkdir() failed: ", lastError);
return false; return false;
}
} }
} }
@ -2174,7 +2195,10 @@ bool FileSystem::CreateDirectoryPath(const char* path, bool recursive)
{ {
lastError = errno; lastError = errno;
if (lastError != EEXIST) if (lastError != EEXIST)
{
Error::SetErrno(error, "mkdir() failed: ", lastError);
return false; return false;
}
} }
} }
@ -2184,6 +2208,7 @@ bool FileSystem::CreateDirectoryPath(const char* path, bool recursive)
else else
{ {
// unhandled error // unhandled error
Error::SetErrno(error, "mkdir() failed: ", lastError);
return false; return false;
} }
} }
@ -2200,14 +2225,19 @@ bool FileSystem::DeleteFilePath(const char* path)
return (unlink(path) == 0); return (unlink(path) == 0);
} }
bool FileSystem::RenamePath(const char* old_path, const char* new_path) bool FileSystem::RenamePath(const char* old_path, const char* new_path, Error* error)
{ {
if (old_path[0] == '\0' || new_path[0] == '\0') if (old_path[0] == '\0' || new_path[0] == '\0')
{
Error::SetStringView(error, "Path is empty.");
return false; return false;
}
if (rename(old_path, new_path) != 0) if (rename(old_path, new_path) != 0)
{ {
Console.Error("rename('%s', '%s') failed: %d", old_path, new_path, errno); const int err = errno;
Error::SetErrno(error, "rename() failed: ", err);
Console.Error("rename('%s', '%s') failed: %d", old_path, new_path, err);
return false; return false;
} }

View File

@ -2,7 +2,9 @@
// SPDX-License-Identifier: LGPL-3.0+ // SPDX-License-Identifier: LGPL-3.0+
#pragma once #pragma once
#include "Pcsx2Defs.h" #include "Pcsx2Defs.h"
#include <cstdio> #include <cstdio>
#include <ctime> #include <ctime>
#include <memory> #include <memory>
@ -88,7 +90,7 @@ namespace FileSystem
bool DeleteFilePath(const char* path); bool DeleteFilePath(const char* path);
/// Rename file /// Rename file
bool RenamePath(const char* OldPath, const char* NewPath); bool RenamePath(const char* OldPath, const char* NewPath, Error* error = nullptr);
/// Deleter functor for managed file pointers /// Deleter functor for managed file pointers
struct FileDeleter struct FileDeleter
@ -134,11 +136,11 @@ namespace FileSystem
/// if the directory already exists, the return value will be true. /// if the directory already exists, the return value will be true.
/// if Recursive is specified, all parent directories will be created /// if Recursive is specified, all parent directories will be created
/// if they do not exist. /// if they do not exist.
bool CreateDirectoryPath(const char* path, bool recursive); bool CreateDirectoryPath(const char* path, bool recursive, Error* error = nullptr);
/// Creates a directory if it doesn't already exist. /// Creates a directory if it doesn't already exist.
/// Returns false if it does not exist and creation failed. /// Returns false if it does not exist and creation failed.
bool EnsureDirectoryExists(const char* path, bool recursive); bool EnsureDirectoryExists(const char* path, bool recursive, Error* error = nullptr);
/// Removes a directory. /// Removes a directory.
bool DeleteDirectory(const char* path); bool DeleteDirectory(const char* path);