Skip to content

Commit

Permalink
Merge pull request #5720 from JosJuice/file-metadata
Browse files Browse the repository at this point in the history
FileUtil: Redesign Exists/IsDirectory/GetSize
  • Loading branch information
leoetlino committed Jul 10, 2017
2 parents 12f6d0b + 5ca3aee commit b6c3479
Show file tree
Hide file tree
Showing 21 changed files with 171 additions and 173 deletions.
138 changes: 70 additions & 68 deletions Source/Core/Common/FileUtil.cpp
Expand Up @@ -51,38 +51,67 @@
// REMEMBER: strdup considered harmful!
namespace File
{
// Returns true if file filename exists
bool Exists(const std::string& filename)
#ifdef _WIN32
FileInfo::FileInfo(const std::string& path)
{
struct stat file_info;
m_exists = _tstat64(UTF8ToTStr(path).c_str(), &m_stat) == 0;
}

#ifdef _WIN32
int result = _tstat64(UTF8ToTStr(filename).c_str(), &file_info);
FileInfo::FileInfo(const char* path) : FileInfo(std::string(path))
{
}
#else
int result = stat(filename.c_str(), &file_info);
FileInfo::FileInfo(const std::string& path) : FileInfo(path.c_str())
{
}

FileInfo::FileInfo(const char* path)
{
m_exists = stat(path, &m_stat) == 0;
}
#endif

return (result == 0);
FileInfo::FileInfo(int fd)
{
m_exists = fstat(fd, &m_stat);
}

// Returns true if filename is a directory
bool IsDirectory(const std::string& filename)
bool FileInfo::Exists() const
{
struct stat file_info;
return m_exists;
}

#ifdef _WIN32
int result = _tstat64(UTF8ToTStr(filename).c_str(), &file_info);
#else
int result = stat(filename.c_str(), &file_info);
#endif
bool FileInfo::IsDirectory() const
{
return m_exists ? S_ISDIR(m_stat.st_mode) : false;
}

if (result < 0)
{
WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s", filename.c_str(), strerror(errno));
return false;
}
bool FileInfo::IsFile() const
{
return m_exists ? !S_ISDIR(m_stat.st_mode) : false;
}

u64 FileInfo::GetSize() const
{
return IsFile() ? m_stat.st_size : 0;
}

return S_ISDIR(file_info.st_mode);
// Returns true if the path exists
bool Exists(const std::string& path)
{
return FileInfo(path).Exists();
}

// Returns true if the path exists and is a directory
bool IsDirectory(const std::string& path)
{
return FileInfo(path).IsDirectory();
}

// Returns true if the path exists and is a file
bool IsFile(const std::string& path)
{
return FileInfo(path).IsFile();
}

// Deletes a given filename, return true on success
Expand All @@ -91,16 +120,18 @@ bool Delete(const std::string& filename)
{
INFO_LOG(COMMON, "Delete: file %s", filename.c_str());

const FileInfo file_info(filename);

// Return true because we care about the file no
// being there, not the actual delete.
if (!Exists(filename))
if (!file_info.Exists())
{
WARN_LOG(COMMON, "Delete: %s does not exist", filename.c_str());
return true;
}

// We can't delete a directory
if (IsDirectory(filename))
if (file_info.IsDirectory())
{
WARN_LOG(COMMON, "Delete failed: %s is a directory", filename.c_str());
return false;
Expand Down Expand Up @@ -163,7 +194,7 @@ bool CreateFullPath(const std::string& fullPath)
int panicCounter = 100;
INFO_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str());

if (File::Exists(fullPath))
if (Exists(fullPath))
{
INFO_LOG(COMMON, "CreateFullPath: path exists %s", fullPath.c_str());
return true;
Expand All @@ -181,7 +212,7 @@ bool CreateFullPath(const std::string& fullPath)

// Include the '/' so the first call is CreateDir("/") rather than CreateDir("")
std::string const subPath(fullPath.substr(0, position + 1));
if (!File::IsDirectory(subPath))
if (!IsDirectory(subPath))
File::CreateDir(subPath);

// A safety check
Expand All @@ -201,7 +232,7 @@ bool DeleteDir(const std::string& filename)
INFO_LOG(COMMON, "DeleteDir: directory %s", filename.c_str());

// check if a directory
if (!File::IsDirectory(filename))
if (!IsDirectory(filename))
{
ERROR_LOG(COMMON, "DeleteDir: Not a directory %s", filename.c_str());
return false;
Expand Down Expand Up @@ -344,46 +375,16 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename)
#endif
}

// Returns the size of filename (64bit)
u64 GetSize(const std::string& filename)
// Returns the size of a file (or returns 0 if the path isn't a file that exists)
u64 GetSize(const std::string& path)
{
if (!Exists(filename))
{
WARN_LOG(COMMON, "GetSize: failed %s: No such file", filename.c_str());
return 0;
}

if (IsDirectory(filename))
{
WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str());
return 0;
}

struct stat buf;
#ifdef _WIN32
if (_tstat64(UTF8ToTStr(filename).c_str(), &buf) == 0)
#else
if (stat(filename.c_str(), &buf) == 0)
#endif
{
DEBUG_LOG(COMMON, "GetSize: %s: %lld", filename.c_str(), (long long)buf.st_size);
return buf.st_size;
}

ERROR_LOG(COMMON, "GetSize: Stat failed %s: %s", filename.c_str(), GetLastErrorMsg().c_str());
return 0;
return FileInfo(path).GetSize();
}

// Overloaded GetSize, accepts file descriptor
u64 GetSize(const int fd)
{
struct stat buf;
if (fstat(fd, &buf) != 0)
{
ERROR_LOG(COMMON, "GetSize: stat failed %i: %s", fd, GetLastErrorMsg().c_str());
return 0;
}
return buf.st_size;
return FileInfo(fd).GetSize();
}

// Overloaded GetSize, accepts FILE*
Expand Down Expand Up @@ -458,7 +459,8 @@ FSTEntry ScanDirectoryTree(const std::string& directory, bool recursive)
continue;
auto physical_name = directory + DIR_SEP + virtual_name;
FSTEntry entry;
entry.isDirectory = IsDirectory(physical_name);
const FileInfo file_info(physical_name);
entry.isDirectory = file_info.IsDirectory();
if (entry.isDirectory)
{
if (recursive)
Expand All @@ -469,7 +471,7 @@ FSTEntry ScanDirectoryTree(const std::string& directory, bool recursive)
}
else
{
entry.size = GetSize(physical_name);
entry.size = file_info.GetSize();
}
entry.virtualName = virtual_name;
entry.physicalName = physical_name;
Expand Down Expand Up @@ -561,9 +563,9 @@ void CopyDir(const std::string& source_path, const std::string& dest_path)
{
if (source_path == dest_path)
return;
if (!File::Exists(source_path))
if (!Exists(source_path))
return;
if (!File::Exists(dest_path))
if (!Exists(dest_path))
File::CreateFullPath(dest_path);

#ifdef _WIN32
Expand Down Expand Up @@ -596,11 +598,11 @@ void CopyDir(const std::string& source_path, const std::string& dest_path)
std::string dest = dest_path + DIR_SEP + virtualName;
if (IsDirectory(source))
{
if (!File::Exists(dest))
if (!Exists(dest))
File::CreateFullPath(dest + DIR_SEP);
CopyDir(source, dest);
}
else if (!File::Exists(dest))
else if (!Exists(dest))
File::Copy(source, dest);
#ifdef _WIN32
} while (FindNextFile(hFind, &ffd) != 0);
Expand Down Expand Up @@ -852,12 +854,12 @@ void SetUserPath(unsigned int dir_index, const std::string& path)
std::string GetThemeDir(const std::string& theme_name)
{
std::string dir = File::GetUserPath(D_THEMES_IDX) + theme_name + "/";
if (File::Exists(dir))
if (Exists(dir))
return dir;

// If the theme doesn't exist in the user dir, load from shared directory
dir = GetSysDirectory() + THEMES_DIR "/" + theme_name + "/";
if (File::Exists(dir))
if (Exists(dir))
return dir;

// If the theme doesn't exist at all, load the default theme
Expand Down
42 changes: 36 additions & 6 deletions Source/Core/Common/FileUtil.h
Expand Up @@ -9,6 +9,8 @@
#include <string>
#include <vector>

#include <sys/stat.h>

#include "Common/CommonTypes.h"
#include "Common/NonCopyable.h"

Expand Down Expand Up @@ -78,14 +80,42 @@ struct FSTEntry
std::vector<FSTEntry> children;
};

// Returns true if file filename exists
bool Exists(const std::string& filename);
// The functions in this class are functionally identical to the standalone functions
// below, but if you are going to be calling more than one of the functions using the
// same path, creating a single FileInfo object and calling its functions multiple
// times is faster than calling standalone functions multiple times.
class FileInfo final
{
public:
explicit FileInfo(const std::string& path);
explicit FileInfo(const char* path);
explicit FileInfo(int fd);

// Returns true if the path exists
bool Exists() const;
// Returns true if the path exists and is a directory
bool IsDirectory() const;
// Returns true if the path exists and is a file
bool IsFile() const;
// Returns the size of a file (or returns 0 if the path doesn't refer to a file)
u64 GetSize() const;

private:
struct stat m_stat;
bool m_exists;
};

// Returns true if the path exists
bool Exists(const std::string& path);

// Returns true if the path exists and is a directory
bool IsDirectory(const std::string& path);

// Returns true if filename is a directory
bool IsDirectory(const std::string& filename);
// Returns true if the path exists and is a file
bool IsFile(const std::string& path);

// Returns the size of filename (64bit)
u64 GetSize(const std::string& filename);
// Returns the size of a file (or returns 0 if the path isn't a file that exists)
u64 GetSize(const std::string& path);

// Overloaded GetSize, accepts file descriptor
u64 GetSize(const int fd);
Expand Down
3 changes: 1 addition & 2 deletions Source/Core/Common/SysConf.cpp
Expand Up @@ -56,8 +56,7 @@ void SysConf::Load()
{
Clear();

if (!File::Exists(m_file_name) || File::GetSize(m_file_name) != SYSCONF_SIZE ||
!LoadFromFile(m_file_name))
if (File::GetSize(m_file_name) != SYSCONF_SIZE || !LoadFromFile(m_file_name))
{
WARN_LOG(CORE, "No valid SYSCONF detected. Creating a new one.");
InsertDefaultEntries();
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/Boot/Boot.cpp
Expand Up @@ -466,8 +466,8 @@ bool CBoot::BootUp(std::unique_ptr<BootParameters> boot)

BootExecutableReader::BootExecutableReader(const std::string& file_name)
{
m_bytes.resize(File::GetSize(file_name));
File::IOFile file{file_name, "rb"};
m_bytes.resize(file.GetSize());
file.ReadBytes(m_bytes.data(), m_bytes.size());
}

Expand Down
3 changes: 0 additions & 3 deletions Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp
Expand Up @@ -52,9 +52,6 @@ void AXUCode::LoadResamplingCoefficients()
for (fidx = 0; fidx < ArraySize(filenames); ++fidx)
{
filename = filenames[fidx];
if (!File::Exists(filename))
continue;

if (File::GetSize(filename) != 0x1000)
continue;

Expand Down
34 changes: 15 additions & 19 deletions Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp
Expand Up @@ -204,30 +204,26 @@ void CEXIIPL::LoadFontFile(const std::string& filename, u32 offset)
if (ipl_rom_path.empty())
ipl_rom_path = FindIPLDump(File::GetSysDirectory() + GC_SYS_DIR);

if (File::Exists(ipl_rom_path))
// If the user has an IPL dump, load the font from it
File::IOFile stream(ipl_rom_path, "rb");
if (!stream)
{
// The user has an IPL dump, load the font from it
File::IOFile stream(ipl_rom_path, "rb");
if (!stream)
return;
// No IPL dump available, load bundled font instead
LoadFileToIPL(filename, offset);
return;
}

// Official Windows-1252 and Shift JIS fonts present on the IPL dumps are 0x2575 and 0x4a24d
// bytes long respectively, so, determine the size of the font being loaded based on the offset
u64 fontsize = (offset == 0x1aff00) ? 0x4a24d : 0x2575;
// Official Windows-1252 and Shift JIS fonts present on the IPL dumps are 0x2575 and 0x4a24d
// bytes long respectively, so, determine the size of the font being loaded based on the offset
u64 fontsize = (offset == 0x1aff00) ? 0x4a24d : 0x2575;

INFO_LOG(BOOT, "Found IPL dump, loading %s font from %s",
((offset == 0x1aff00) ? "Shift JIS" : "Windows-1252"), (ipl_rom_path).c_str());
INFO_LOG(BOOT, "Found IPL dump, loading %s font from %s",
((offset == 0x1aff00) ? "Shift JIS" : "Windows-1252"), (ipl_rom_path).c_str());

stream.Seek(offset, 0);
stream.ReadBytes(m_pIPL + offset, fontsize);
stream.Seek(offset, 0);
stream.ReadBytes(m_pIPL + offset, fontsize);

m_FontsLoaded = true;
}
else
{
// No IPL dump available, load bundled font instead
LoadFileToIPL(filename, offset);
}
m_FontsLoaded = true;
}

void CEXIIPL::SetCS(int _iCS)
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp
Expand Up @@ -176,11 +176,12 @@ void CEXIMemoryCard::SetupGciFolder(u16 sizeMb)
strDirectoryName = strDirectoryName + SConfig::GetDirectoryForRegion(region) + DIR_SEP +
StringFromFormat("Card %c", 'A' + card_index);

if (!File::Exists(strDirectoryName)) // first use of memcard folder, migrate automatically
const File::FileInfo file_info(strDirectoryName);
if (!file_info.Exists()) // first use of memcard folder, migrate automatically
{
MigrateFromMemcardFile(strDirectoryName + DIR_SEP, card_index);
}
else if (!File::IsDirectory(strDirectoryName))
else if (!file_info.IsDirectory())
{
if (File::Rename(strDirectoryName, strDirectoryName + ".original"))
{
Expand Down

0 comments on commit b6c3479

Please sign in to comment.