mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Everything: Get rid of wx entirely from the Qt build
This commit is contained in:
committed by
refractionpcsx2
parent
893b3c629d
commit
ea051c6d5f
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include "Path.h"
|
||||
#include "Assertions.h"
|
||||
#include "Console.h"
|
||||
#include "StringUtil.h"
|
||||
@@ -21,6 +22,7 @@
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <mach-o/dyld.h>
|
||||
@@ -33,12 +35,10 @@
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "RedtapeWindows.h"
|
||||
#include <winioctl.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
// We can't guarantee that windows.h isn't included before here, so we have to undef.
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
#if defined(_UWP)
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
@@ -87,7 +87,50 @@ static inline bool FileSystemCharacterIsSane(char c, bool StripSlashes)
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileSystem::SanitizeFileName(char* Destination, u32 cbDestination, const char* FileName, bool StripSlashes /* = true */)
|
||||
template<typename T>
|
||||
static inline void PathAppendString(std::string& dst, const T& src)
|
||||
{
|
||||
if (dst.capacity() < (dst.length() + src.length()))
|
||||
dst.reserve(dst.length() + src.length());
|
||||
|
||||
bool last_separator = (!dst.empty() && dst.back() == FS_OSPATH_SEPARATOR_CHARACTER);
|
||||
|
||||
size_t index = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
// special case for UNC paths here
|
||||
if (dst.empty() && src.length() >= 3 && src[0] == '\\' && src[1] == '\\' && src[2] != '\\')
|
||||
{
|
||||
dst.append("\\\\");
|
||||
index = 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (; index < src.length(); index++)
|
||||
{
|
||||
const char ch = src[index];
|
||||
|
||||
#ifdef _WIN32
|
||||
// convert forward slashes to backslashes
|
||||
if (ch == '\\' || ch == '/')
|
||||
#else
|
||||
if (ch == '/')
|
||||
#endif
|
||||
{
|
||||
if (last_separator)
|
||||
continue;
|
||||
last_separator = true;
|
||||
dst.push_back(FS_OSPATH_SEPARATOR_CHARACTER);
|
||||
}
|
||||
else
|
||||
{
|
||||
last_separator = false;
|
||||
dst.push_back(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Path::SanitizeFileName(char* Destination, u32 cbDestination, const char* FileName, bool StripSlashes /* = true */)
|
||||
{
|
||||
u32 i;
|
||||
u32 fileNameLength = static_cast<u32>(std::strlen(FileName));
|
||||
@@ -112,7 +155,7 @@ void FileSystem::SanitizeFileName(char* Destination, u32 cbDestination, const ch
|
||||
}
|
||||
}
|
||||
|
||||
void FileSystem::SanitizeFileName(std::string& Destination, bool StripSlashes /* = true*/)
|
||||
void Path::SanitizeFileName(std::string& Destination, bool StripSlashes /* = true*/)
|
||||
{
|
||||
const std::size_t len = Destination.length();
|
||||
for (std::size_t i = 0; i < len; i++)
|
||||
@@ -122,26 +165,129 @@ void FileSystem::SanitizeFileName(std::string& Destination, bool StripSlashes /*
|
||||
}
|
||||
}
|
||||
|
||||
bool FileSystem::IsAbsolutePath(const std::string_view& path)
|
||||
bool Path::IsAbsolute(const std::string_view& path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return (path.length() >= 3 && ((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) &&
|
||||
path[1] == ':' && (path[2] == '/' || path[2] == '\\'));
|
||||
path[1] == ':' && (path[2] == '/' || path[2] == '\\')) || (path.length() >= 3 && path[0] == '\\' && path[1] == '\\');
|
||||
#else
|
||||
return (path.length() >= 1 && path[0] == '/');
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string_view FileSystem::GetExtension(const std::string_view& path)
|
||||
std::string Path::ToNativePath(const std::string_view& path)
|
||||
{
|
||||
std::string ret;
|
||||
PathAppendString(ret, path);
|
||||
|
||||
// remove trailing slashes
|
||||
if (ret.length() > 1)
|
||||
{
|
||||
while (ret.back() == FS_OSPATH_SEPARATOR_CHARACTER)
|
||||
ret.pop_back();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Path::ToNativePath(std::string* path)
|
||||
{
|
||||
*path = Path::ToNativePath(*path);
|
||||
}
|
||||
|
||||
std::string Path::Canonicalize(const std::string_view& path)
|
||||
{
|
||||
std::vector<std::string_view> components = Path::SplitNativePath(path);
|
||||
std::vector<std::string_view> new_components;
|
||||
new_components.reserve(components.size());
|
||||
for (const std::string_view& component : components)
|
||||
{
|
||||
if (component == ".")
|
||||
{
|
||||
// current directory, so it can be skipped, unless it's the only component
|
||||
if (components.size() == 1)
|
||||
new_components.push_back(std::move(component));
|
||||
}
|
||||
else if (component == "..")
|
||||
{
|
||||
// parent directory, pop one off if we're not at the beginning, otherwise preserve.
|
||||
if (!new_components.empty())
|
||||
new_components.pop_back();
|
||||
else
|
||||
new_components.push_back(std::move(component));
|
||||
}
|
||||
else
|
||||
{
|
||||
// anything else, preserve
|
||||
new_components.push_back(std::move(component));
|
||||
}
|
||||
}
|
||||
|
||||
return Path::JoinNativePath(new_components);
|
||||
}
|
||||
|
||||
void Path::Canonicalize(std::string* path)
|
||||
{
|
||||
*path = Canonicalize(*path);
|
||||
}
|
||||
|
||||
std::string Path::MakeRelative(const std::string_view& path, const std::string_view& relative_to)
|
||||
{
|
||||
// simple algorithm, we just work on the components. could probably be better, but it'll do for now.
|
||||
std::vector<std::string_view> path_components(SplitNativePath(path));
|
||||
std::vector<std::string_view> relative_components(SplitNativePath(relative_to));
|
||||
std::vector<std::string_view> new_components;
|
||||
|
||||
// both must be absolute paths
|
||||
if (Path::IsAbsolute(path) && Path::IsAbsolute(relative_to))
|
||||
{
|
||||
// find the number of same components
|
||||
size_t num_same = 0;
|
||||
for (size_t i = 0; i < path_components.size() && i < relative_components.size(); i++)
|
||||
{
|
||||
if (path_components[i] == relative_components[i])
|
||||
num_same++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// we need at least one same component
|
||||
if (num_same > 0)
|
||||
{
|
||||
// from the relative_to directory, back up to the start of the common components
|
||||
const size_t num_ups = relative_components.size() - num_same;
|
||||
for (size_t i = 0; i < num_ups; i++)
|
||||
new_components.emplace_back("..");
|
||||
|
||||
// and add the remainder of the path components
|
||||
for (size_t i = num_same; i < path_components.size(); i++)
|
||||
new_components.push_back(std::move(path_components[i]));
|
||||
}
|
||||
else
|
||||
{
|
||||
// no similarity
|
||||
new_components = std::move(path_components);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// not absolute
|
||||
new_components = std::move(path_components);
|
||||
}
|
||||
|
||||
return JoinNativePath(new_components);
|
||||
}
|
||||
|
||||
std::string_view Path::GetExtension(const std::string_view& path)
|
||||
{
|
||||
const std::string_view::size_type pos = path.rfind('.');
|
||||
if (pos == std::string_view::npos)
|
||||
return path;
|
||||
|
||||
return path.substr(pos + 1);
|
||||
return std::string_view();
|
||||
else
|
||||
return path.substr(pos + 1);
|
||||
}
|
||||
|
||||
std::string_view FileSystem::StripExtension(const std::string_view& path)
|
||||
std::string_view Path::StripExtension(const std::string_view& path)
|
||||
{
|
||||
const std::string_view::size_type pos = path.rfind('.');
|
||||
if (pos == std::string_view::npos)
|
||||
@@ -150,7 +296,7 @@ std::string_view FileSystem::StripExtension(const std::string_view& path)
|
||||
return path.substr(0, pos);
|
||||
}
|
||||
|
||||
std::string FileSystem::ReplaceExtension(const std::string_view& path, const std::string_view& new_extension)
|
||||
std::string Path::ReplaceExtension(const std::string_view& path, const std::string_view& new_extension)
|
||||
{
|
||||
const std::string_view::size_type pos = path.rfind('.');
|
||||
if (pos == std::string_view::npos)
|
||||
@@ -183,10 +329,10 @@ static std::string_view::size_type GetLastSeperatorPosition(const std::string_vi
|
||||
|
||||
std::string FileSystem::GetDisplayNameFromPath(const std::string_view& path)
|
||||
{
|
||||
return std::string(GetFileNameFromPath(path));
|
||||
return std::string(Path::GetFileName(path));
|
||||
}
|
||||
|
||||
std::string_view FileSystem::GetPathDirectory(const std::string_view& path)
|
||||
std::string_view Path::GetDirectory(const std::string_view& path)
|
||||
{
|
||||
const std::string::size_type pos = GetLastSeperatorPosition(path, false);
|
||||
if (pos == std::string_view::npos)
|
||||
@@ -195,7 +341,7 @@ std::string_view FileSystem::GetPathDirectory(const std::string_view& path)
|
||||
return path.substr(0, pos);
|
||||
}
|
||||
|
||||
std::string_view FileSystem::GetFileNameFromPath(const std::string_view& path)
|
||||
std::string_view Path::GetFileName(const std::string_view& path)
|
||||
{
|
||||
const std::string_view::size_type pos = GetLastSeperatorPosition(path, true);
|
||||
if (pos == std::string_view::npos)
|
||||
@@ -204,9 +350,9 @@ std::string_view FileSystem::GetFileNameFromPath(const std::string_view& path)
|
||||
return path.substr(pos);
|
||||
}
|
||||
|
||||
std::string_view FileSystem::GetFileTitleFromPath(const std::string_view& path)
|
||||
std::string_view Path::GetFileTitle(const std::string_view& path)
|
||||
{
|
||||
const std::string_view filename(GetFileNameFromPath(path));
|
||||
const std::string_view filename(GetFileName(path));
|
||||
const std::string::size_type pos = filename.rfind('.');
|
||||
if (pos == std::string_view::npos)
|
||||
return filename;
|
||||
@@ -214,7 +360,86 @@ std::string_view FileSystem::GetFileTitleFromPath(const std::string_view& path)
|
||||
return filename.substr(0, pos);
|
||||
}
|
||||
|
||||
std::vector<std::string_view> FileSystem::SplitWindowsPath(const std::string_view& path)
|
||||
std::string Path::ChangeFileName(const std::string_view& path, const std::string_view& new_filename)
|
||||
{
|
||||
std::string ret;
|
||||
PathAppendString(ret, path);
|
||||
|
||||
const std::string_view::size_type pos = GetLastSeperatorPosition(ret, true);
|
||||
if (pos == std::string_view::npos)
|
||||
{
|
||||
ret.clear();
|
||||
PathAppendString(ret, new_filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!new_filename.empty())
|
||||
{
|
||||
ret.erase(pos);
|
||||
PathAppendString(ret, new_filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.erase(pos - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Path::ChangeFileName(std::string* path, const std::string_view& new_filename)
|
||||
{
|
||||
*path = ChangeFileName(*path, new_filename);
|
||||
}
|
||||
|
||||
std::string Path::AppendDirectory(const std::string_view& path, const std::string_view& new_dir)
|
||||
{
|
||||
std::string ret;
|
||||
if (!new_dir.empty())
|
||||
{
|
||||
const std::string_view::size_type pos = GetLastSeperatorPosition(path, true);
|
||||
|
||||
ret.reserve(path.length() + new_dir.length() + 1);
|
||||
if (pos != std::string_view::npos)
|
||||
PathAppendString(ret, path.substr(0, pos));
|
||||
|
||||
while (!ret.empty() && ret.back() == FS_OSPATH_SEPARATOR_CHARACTER)
|
||||
ret.pop_back();
|
||||
|
||||
if (!ret.empty())
|
||||
ret += FS_OSPATH_SEPARATOR_CHARACTER;
|
||||
|
||||
PathAppendString(ret, new_dir);
|
||||
|
||||
if (pos != std::string_view::npos)
|
||||
{
|
||||
const std::string_view filepart(path.substr(pos));
|
||||
if (!filepart.empty())
|
||||
{
|
||||
ret += FS_OSPATH_SEPARATOR_CHARACTER;
|
||||
PathAppendString(ret, filepart);
|
||||
}
|
||||
}
|
||||
else if (!path.empty())
|
||||
{
|
||||
ret += FS_OSPATH_SEPARATOR_CHARACTER;
|
||||
PathAppendString(ret, path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PathAppendString(ret, path);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Path::AppendDirectory(std::string* path, const std::string_view& new_dir)
|
||||
{
|
||||
*path = AppendDirectory(*path, new_dir);
|
||||
}
|
||||
|
||||
std::vector<std::string_view> Path::SplitWindowsPath(const std::string_view& path)
|
||||
{
|
||||
std::vector<std::string_view> parts;
|
||||
|
||||
@@ -242,9 +467,48 @@ std::vector<std::string_view> FileSystem::SplitWindowsPath(const std::string_vie
|
||||
return parts;
|
||||
}
|
||||
|
||||
std::vector<std::string_view> FileSystem::SplitNativePath(const std::string_view& path)
|
||||
std::string Path::JoinWindowsPath(const std::vector<std::string_view>& components)
|
||||
{
|
||||
return StringUtil::SplitString(path, FS_OSPATH_SEPARATOR_CHARACTER, true);
|
||||
return StringUtil::JoinString(components.begin(), components.end(), '\\');
|
||||
}
|
||||
|
||||
std::vector<std::string_view> Path::SplitNativePath(const std::string_view& path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return SplitWindowsPath(path);
|
||||
#else
|
||||
std::vector<std::string_view> parts;
|
||||
|
||||
std::string::size_type start = 0;
|
||||
std::string::size_type pos = 0;
|
||||
while (pos < path.size())
|
||||
{
|
||||
if (path[pos] != '/')
|
||||
{
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip consecutive separators
|
||||
// for unix, we create an empty element at the beginning when it's an absolute path
|
||||
// that way, when it's re-joined later, we preserve the starting slash.
|
||||
if (pos != start || pos == 0)
|
||||
parts.push_back(path.substr(start, pos - start));
|
||||
|
||||
pos++;
|
||||
start = pos;
|
||||
}
|
||||
|
||||
if (start != pos)
|
||||
parts.push_back(path.substr(start));
|
||||
|
||||
return parts;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string Path::JoinNativePath(const std::vector<std::string_view>& components)
|
||||
{
|
||||
return StringUtil::JoinString(components.begin(), components.end(), FS_OSPATH_SEPARATOR_CHARACTER);
|
||||
}
|
||||
|
||||
std::vector<std::string> FileSystem::GetRootDirectoryList()
|
||||
@@ -297,7 +561,7 @@ std::vector<std::string> FileSystem::GetRootDirectoryList()
|
||||
return results;
|
||||
}
|
||||
|
||||
std::string FileSystem::BuildRelativePath(const std::string_view& filename, const std::string_view& new_filename)
|
||||
std::string Path::BuildRelativePath(const std::string_view& filename, const std::string_view& new_filename)
|
||||
{
|
||||
std::string new_string;
|
||||
|
||||
@@ -308,10 +572,21 @@ std::string FileSystem::BuildRelativePath(const std::string_view& filename, cons
|
||||
return new_string;
|
||||
}
|
||||
|
||||
std::string FileSystem::JoinPath(const std::string_view& base, const std::string_view& next)
|
||||
std::string Path::Combine(const std::string_view& base, const std::string_view& next)
|
||||
{
|
||||
// TODO: Rewrite this natively when wxDirName is dropped.
|
||||
return Path::CombineStdString(base, next);
|
||||
std::string ret;
|
||||
ret.reserve(base.length() + next.length() + 1);
|
||||
|
||||
PathAppendString(ret, base);
|
||||
while (!ret.empty() && ret.back() == FS_OSPATH_SEPARATOR_CHARACTER)
|
||||
ret.pop_back();
|
||||
|
||||
ret += FS_OSPATH_SEPARATOR_CHARACTER;
|
||||
PathAppendString(ret, next);
|
||||
while (!ret.empty() && ret.back() == FS_OSPATH_SEPARATOR_CHARACTER)
|
||||
ret.pop_back();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef _UWP
|
||||
@@ -631,6 +906,49 @@ bool FileSystem::RecursiveDeleteDirectory(const char* path)
|
||||
return DeleteDirectory(path);
|
||||
}
|
||||
|
||||
bool FileSystem::CopyFilePath(const char* source, const char* destination, bool replace)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
// TODO: There's technically a race here between checking and opening the file..
|
||||
// But fopen doesn't specify any way to say "don't create if it exists"...
|
||||
if (!replace && FileExists(destination))
|
||||
return false;
|
||||
|
||||
auto in_fp = OpenManagedCFile(source, "rb");
|
||||
if (!in_fp)
|
||||
return false;
|
||||
|
||||
auto out_fp = OpenManagedCFile(destination, "wb");
|
||||
if (!out_fp)
|
||||
return false;
|
||||
|
||||
u8 buf[4096];
|
||||
while (!std::feof(in_fp.get()))
|
||||
{
|
||||
size_t bytes_in = std::fread(buf, 1, sizeof(buf), in_fp.get());
|
||||
if ((bytes_in == 0 && !std::feof(in_fp.get())) ||
|
||||
(bytes_in > 0 && std::fwrite(buf, 1, bytes_in, out_fp.get()) != bytes_in))
|
||||
{
|
||||
out_fp.reset();
|
||||
DeleteFilePath(destination);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (std::fflush(out_fp.get()) != 0)
|
||||
{
|
||||
out_fp.reset();
|
||||
DeleteFilePath(destination);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return CopyFileW(StringUtil::UTF8StringToWideString(source).c_str(),
|
||||
StringUtil::UTF8StringToWideString(destination).c_str(), !replace);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static u32 TranslateWin32Attributes(u32 Win32Attributes)
|
||||
@@ -783,6 +1101,7 @@ static u32 RecursiveFindFiles(const char* origin_path, const char* parent_path,
|
||||
outData.FileName = utf8_filename;
|
||||
}
|
||||
|
||||
outData.CreationTime = ConvertFileTimeToUnixTime(wfd.ftCreationTime);
|
||||
outData.ModificationTime = ConvertFileTimeToUnixTime(wfd.ftLastWriteTime);
|
||||
outData.Size = (static_cast<u64>(wfd.nFileSizeHigh) << 32) | static_cast<u64>(wfd.nFileSizeLow);
|
||||
|
||||
@@ -904,6 +1223,7 @@ bool FileSystem::StatFile(const char* path, FILESYSTEM_STAT_DATA* sd)
|
||||
|
||||
// fill in the stat data
|
||||
sd->Attributes = TranslateWin32Attributes(bhfi.dwFileAttributes);
|
||||
sd->CreationTime = ConvertFileTimeToUnixTime(bhfi.ftCreationTime);
|
||||
sd->ModificationTime = ConvertFileTimeToUnixTime(bhfi.ftLastWriteTime);
|
||||
sd->Size = static_cast<s64>(((u64)bhfi.nFileSizeHigh) << 32 | (u64)bhfi.nFileSizeLow);
|
||||
return true;
|
||||
@@ -913,6 +1233,7 @@ bool FileSystem::StatFile(const char* path, FILESYSTEM_STAT_DATA* sd)
|
||||
return false;
|
||||
|
||||
sd->Attributes = TranslateWin32Attributes(fad.dwFileAttributes);
|
||||
sd->CreationTime = ConvertFileTimeToUnixTime(fad.ftCreationTime);
|
||||
sd->ModificationTime = ConvertFileTimeToUnixTime(fad.ftLastWriteTime);
|
||||
sd->Size = static_cast<s64>(((u64)fad.nFileSizeHigh) << 32 | (u64)fad.nFileSizeLow);
|
||||
return true;
|
||||
@@ -930,6 +1251,7 @@ bool FileSystem::StatFile(std::FILE* fp, FILESYSTEM_STAT_DATA* sd)
|
||||
return false;
|
||||
|
||||
// parse attributes
|
||||
sd->CreationTime = st.st_ctime;
|
||||
sd->ModificationTime = st.st_mtime;
|
||||
sd->Attributes = 0;
|
||||
if ((st.st_mode & _S_IFMT) == _S_IFDIR)
|
||||
@@ -988,6 +1310,37 @@ bool FileSystem::DirectoryExists(const char* path)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileSystem::DirectoryIsEmpty(const char* path)
|
||||
{
|
||||
std::wstring wpath(StringUtil::UTF8StringToWideString(path));
|
||||
wpath += L"\\*";
|
||||
|
||||
WIN32_FIND_DATAW wfd;
|
||||
#ifndef _UWP
|
||||
HANDLE hFind = FindFirstFileW(wpath.c_str(), &wfd);
|
||||
#else
|
||||
HANDLE hFind = FindFirstFileExFromAppW(wpath.c_str(), FindExInfoBasic, &wfd, FindExSearchNameMatch, nullptr, 0);
|
||||
#endif
|
||||
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
return true;
|
||||
|
||||
do
|
||||
{
|
||||
if (wfd.cFileName[0] == L'.')
|
||||
{
|
||||
if (wfd.cFileName[1] == L'\0' || (wfd.cFileName[1] == L'.' && wfd.cFileName[2] == L'\0'))
|
||||
continue;
|
||||
}
|
||||
|
||||
FindClose(hFind);
|
||||
return false;
|
||||
} while (FindNextFileW(hFind, &wfd));
|
||||
|
||||
FindClose(hFind);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileSystem::CreateDirectoryPath(const char* Path, bool Recursive)
|
||||
{
|
||||
const std::wstring wpath(StringUtil::UTF8StringToWideString(Path));
|
||||
@@ -1317,6 +1670,7 @@ static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, co
|
||||
}
|
||||
|
||||
outData.Size = static_cast<u64>(sDir.st_size);
|
||||
outData.CreationTime = sDir.st_ctime;
|
||||
outData.ModificationTime = sDir.st_mtime;
|
||||
|
||||
// match the filename
|
||||
@@ -1400,6 +1754,7 @@ bool FileSystem::StatFile(const char* path, FILESYSTEM_STAT_DATA* sd)
|
||||
return false;
|
||||
|
||||
// parse attributes
|
||||
sd->CreationTime = sysStatData.st_ctime;
|
||||
sd->ModificationTime = sysStatData.st_mtime;
|
||||
sd->Attributes = 0;
|
||||
if (S_ISDIR(sysStatData.st_mode))
|
||||
@@ -1432,6 +1787,7 @@ bool FileSystem::StatFile(std::FILE* fp, FILESYSTEM_STAT_DATA* sd)
|
||||
return false;
|
||||
|
||||
// parse attributes
|
||||
sd->CreationTime = sysStatData.st_ctime;
|
||||
sd->ModificationTime = sysStatData.st_mtime;
|
||||
sd->Attributes = 0;
|
||||
if (S_ISDIR(sysStatData.st_mode))
|
||||
@@ -1491,6 +1847,30 @@ bool FileSystem::DirectoryExists(const char* path)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileSystem::DirectoryIsEmpty(const char* path)
|
||||
{
|
||||
DIR* pDir = opendir(path);
|
||||
if (pDir == nullptr)
|
||||
return true;
|
||||
|
||||
// iterate results
|
||||
struct dirent* pDirEnt;
|
||||
while ((pDirEnt = readdir(pDir)) != nullptr)
|
||||
{
|
||||
if (pDirEnt->d_name[0] == '.')
|
||||
{
|
||||
if (pDirEnt->d_name[1] == '\0' || (pDirEnt->d_name[1] == '.' && pDirEnt->d_name[2] == '\0'))
|
||||
continue;
|
||||
}
|
||||
|
||||
closedir(pDir);
|
||||
return false;
|
||||
}
|
||||
|
||||
closedir(pDir);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileSystem::CreateDirectoryPath(const char* path, bool recursive)
|
||||
{
|
||||
// has a path
|
||||
|
||||
Reference in New Issue
Block a user