Merge GetFileInfo/GetFileDetails into GetFileInfo

This commit is contained in:
Henrik Rydgård 2021-04-25 20:52:29 +02:00
parent 08843673d9
commit 77b8a14770
9 changed files with 81 additions and 122 deletions

View File

@ -41,6 +41,13 @@ bool GetFileInfo(const char *path, FileInfo * fileInfo) {
fileInfo->fullName = path;
#ifdef _WIN32
auto FiletimeToStatTime = [](FILETIME ft) {
const int windowsTickResolution = 10000000;
const int64_t secToUnixEpoch = 11644473600LL;
int64_t ticks = ((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
return (int64_t)(ticks / windowsTickResolution - secToUnixEpoch);
};
WIN32_FILE_ATTRIBUTE_DATA attrs;
if (!GetFileAttributesExW(ConvertUTF8ToWString(path).c_str(), GetFileExInfoStandard, &attrs)) {
fileInfo->size = 0;
@ -52,16 +59,25 @@ bool GetFileInfo(const char *path, FileInfo * fileInfo) {
fileInfo->isDirectory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
fileInfo->isWritable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
fileInfo->exists = true;
fileInfo->atime = FiletimeToStatTime(attrs.ftLastAccessTime);
fileInfo->mtime = FiletimeToStatTime(attrs.ftLastWriteTime);
fileInfo->ctime = FiletimeToStatTime(attrs.ftCreationTime);
if (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
fileInfo->access = 0444; // Read
} else {
fileInfo->access = 0666; // Read/Write
}
if (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
fileInfo->access |= 0111; // Execute
}
#else
std::string copy(path);
#if (defined __ANDROID__) && (__ANDROID_API__ < 21)
struct stat file_info;
int result = stat(copy.c_str(), &file_info);
int result = stat(path, &file_info);
#else
struct stat64 file_info;
int result = stat64(copy.c_str(), &file_info);
int result = stat64(path, &file_info);
#endif
if (result < 0) {
fileInfo->exists = false;
@ -72,6 +88,10 @@ bool GetFileInfo(const char *path, FileInfo * fileInfo) {
fileInfo->isWritable = false;
fileInfo->size = file_info.st_size;
fileInfo->exists = true;
fileInfo->atime = file_info.st_atime;
fileInfo->mtime = file_info.st_mtime;
fileInfo->ctime = file_info.st_ctime;
fileInfo->access = file_info.st_mode & 0x1ff;
// HACK: approximation
if (file_info.st_mode & 0200)
fileInfo->isWritable = true;
@ -79,14 +99,16 @@ bool GetFileInfo(const char *path, FileInfo * fileInfo) {
return true;
}
std::string getFileExtension(const std::string & fn) {
int pos = (int)fn.rfind(".");
if (pos < 0) return "";
std::string ext = fn.substr(pos + 1);
for (size_t i = 0; i < ext.size(); i++) {
ext[i] = tolower(ext[i]);
bool GetModifTime(const std::string & filename, tm & return_time) {
memset(&return_time, 0, sizeof(return_time));
FileInfo info;
if (GetFileInfo(filename.c_str(), &info)) {
time_t t = info.mtime;
localtime_r((time_t*)&t, &return_time);
return true;
} else {
return false;
}
return ext;
}
bool FileInfo::operator <(const FileInfo & other) const {
@ -173,7 +195,7 @@ size_t GetFilesInDir(const char *directory, std::vector<FileInfo> * files, const
info.size = 0;
info.isWritable = false; // TODO - implement some kind of check
if (!info.isDirectory) {
std::string ext = getFileExtension(info.fullName);
std::string ext = GetFileExtension(info.fullName);
if (filter) {
if (filters.find(ext) == filters.end())
continue;
@ -241,4 +263,4 @@ std::vector<std::string> getWindowsDrives()
}
#endif
}
} // namespace File

View File

@ -19,12 +19,15 @@ struct FileInfo {
bool isWritable;
uint64_t size;
uint64_t atime;
uint64_t mtime;
uint64_t ctime;
uint32_t access; // st_mode & 0x1ff
bool operator <(const FileInfo &other) const;
};
std::string getFileExtension(const std::string &fn);
bool GetFileInfo(const char *path, FileInfo *fileInfo);
FILE *openCFile(const std::string &filename, const char *mode);
enum {
GETFILES_GETHIDDEN = 1

View File

@ -501,73 +501,6 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
#endif
}
#ifdef _WIN32
static int64_t FiletimeToStatTime(FILETIME ft) {
const int windowsTickResolution = 10000000;
const int64_t secToUnixEpoch = 11644473600LL;
int64_t ticks = ((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
return (int64_t)(ticks / windowsTickResolution - secToUnixEpoch);
}
#endif
// Returns file attributes.
bool GetFileDetails(const std::string &filename, FileDetails *details) {
#ifdef _WIN32
WIN32_FILE_ATTRIBUTE_DATA attr;
if (!GetFileAttributesEx(ConvertUTF8ToWString(filename).c_str(), GetFileExInfoStandard, &attr))
return false;
details->isDirectory = (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
details->size = ((uint64_t)attr.nFileSizeHigh << 32) | (uint64_t)attr.nFileSizeLow;
details->atime = FiletimeToStatTime(attr.ftLastAccessTime);
details->mtime = FiletimeToStatTime(attr.ftLastWriteTime);
details->ctime = FiletimeToStatTime(attr.ftCreationTime);
if (attr.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
details->access = 0444; // Read
} else {
details->access = 0666; // Read/Write
}
if (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
details->access |= 0111; // Execute
}
return true;
#else
if (!Exists(filename)) {
return false;
}
#if __ANDROID__ && __ANDROID_API__ < 21
struct stat buf;
if (stat(filename.c_str(), &buf) == 0) {
#else
struct stat64 buf;
if (stat64(filename.c_str(), &buf) == 0) {
#endif
details->size = buf.st_size;
details->isDirectory = S_ISDIR(buf.st_mode);
details->atime = buf.st_atime;
details->mtime = buf.st_mtime;
details->ctime = buf.st_ctime;
details->access = buf.st_mode & 0x1ff;
return true;
} else {
return false;
}
#endif
}
bool GetModifTime(const std::string &filename, tm &return_time) {
memset(&return_time, 0, sizeof(return_time));
FileDetails details;
if (GetFileDetails(filename, &details)) {
time_t t = details.mtime;
localtime_r((time_t*)&t, &return_time);
return true;
} else {
return false;
}
}
std::string GetDir(const std::string &path) {
if (path == "/")
return path;
@ -594,6 +527,18 @@ std::string GetFilename(std::string path) {
return path;
}
std::string GetFileExtension(const std::string & fn) {
size_t pos = fn.rfind(".");
if (pos == std::string::npos) {
return "";
}
std::string ext = fn.substr(pos + 1);
for (size_t i = 0; i < ext.size(); i++) {
ext[i] = tolower(ext[i]);
}
return ext;
}
// Returns the size of file (64bit)
// TODO: Add a way to return an error.
uint64_t GetFileSize(const std::string &filename) {
@ -668,7 +613,6 @@ uint64_t GetFileSize(FILE *f)
bool CreateEmptyFile(const std::string &filename)
{
INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str());
FILE *pFile = OpenCFile(filename, "wb");
if (!pFile) {
ERROR_LOG(COMMON, "CreateEmptyFile: failed %s: %s", filename.c_str(), GetLastErrorMsg().c_str());
@ -765,26 +709,28 @@ void CopyDir(const std::string &source_path, const std::string &dest_path)
DIR *dirp = opendir(source_path.c_str());
if (!dirp) return;
while ((result = readdir(dirp)))
{
while ((result = readdir(dirp))) {
const std::string virtualName(result->d_name);
// check for "." and ".."
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
((virtualName[0] == '.') && (virtualName[1] == '.') &&
(virtualName[2] == '\0')))
(virtualName[2] == '\0'))) {
continue;
}
std::string source, dest;
source = source_path + virtualName;
dest = dest_path + virtualName;
if (IsDirectory(source))
{
if (IsDirectory(source)) {
source += '/';
dest += '/';
if (!File::Exists(dest)) File::CreateFullPath(dest);
if (!File::Exists(dest)) {
File::CreateFullPath(dest);
}
CopyDir(source, dest);
} else if (!File::Exists(dest)) {
File::Copy(source, dest);
}
else if (!File::Exists(dest)) File::Copy(source, dest);
}
closedir(dirp);
#else
@ -792,7 +738,7 @@ void CopyDir(const std::string &source_path, const std::string &dest_path)
#endif
}
void openIniFile(const std::string& fileName) {
void OpenFileInEditor(const std::string& fileName) {
#if defined(_WIN32)
#if PPSSPP_PLATFORM(UWP)
// Do nothing.

View File

@ -36,15 +36,6 @@ inline struct tm* localtime_r(const time_t *clock, struct tm *result) {
namespace File {
struct FileDetails {
bool isDirectory;
uint64_t size;
uint64_t atime;
uint64_t mtime;
uint64_t ctime;
uint32_t access; // st_mode & 0x1ff
};
// Mostly to handle utf-8 filenames better on Windows.
FILE *OpenCFile(const std::string &filename, const char *mode);
bool OpenCPPFile(std::fstream & stream, const std::string &filename, std::ios::openmode mode);
@ -58,8 +49,8 @@ bool Exists(const std::string &filename);
// Returns true if filename is a directory
bool IsDirectory(const std::string &filename);
// Returns file attributes.
bool GetFileDetails(const std::string &filename, FileDetails *details);
// Parses the extension out from a filename.
std::string GetFileExtension(const std::string &filename);
// Extracts the directory from a path.
std::string GetDir(const std::string &path);
@ -101,18 +92,14 @@ bool CreateEmptyFile(const std::string &filename);
// deletes the given directory and anything under it. Returns true on success.
bool DeleteDirRecursively(const std::string &directory);
// Returns the current directory
std::string GetCurrentDir();
// Create directory and copy contents (does not overwrite existing files)
void CopyDir(const std::string &source_path, const std::string &dest_path);
// Opens ini file (cheats, texture replacements etc.)
void openIniFile(const std::string& fileName);
// Set the current directory to given directory
bool SetCurrentDir(const std::string &directory);
// TODO: Belongs in System or something.
void OpenFileInEditor(const std::string& fileName);
// TODO: Belongs in System or something.
const std::string &GetExeDirectory();

View File

@ -8,6 +8,7 @@
#include "Common/Net/URL.h"
#include "Common/File/PathBrowser.h"
#include "Common/File/FileUtil.h"
#include "Common/StringUtils.h"
#include "Common/TimeUtil.h"
#include "Common/Log.h"
@ -110,7 +111,7 @@ std::vector<File::FileInfo> ApplyFilter(std::vector<File::FileInfo> files, const
auto pred = [&](const File::FileInfo &info) {
if (info.isDirectory || !filter)
return false;
std::string ext = File::getFileExtension(info.fullName);
std::string ext = File::GetFileExtension(info.fullName);
return filters.find(ext) == filters.end();
};
files.erase(std::remove_if(files.begin(), files.end(), pred), files.end());

View File

@ -751,15 +751,15 @@ PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) {
x.exists = true;
if (x.type != FILETYPE_DIRECTORY) {
File::FileDetails details;
if (!File::GetFileDetails(fullName, &details)) {
File::FileInfo info;
if (!File::GetFileInfo(fullName.c_str(), &info)) {
ERROR_LOG(FILESYS, "DirectoryFileSystem::GetFileInfo: GetFileDetails failed: %s", fullName.c_str());
} else {
x.size = details.size;
x.access = details.access;
time_t atime = details.atime;
time_t ctime = details.ctime;
time_t mtime = details.mtime;
x.size = info.size;
x.access = info.access;
time_t atime = info.atime;
time_t ctime = info.ctime;
time_t mtime = info.mtime;
localtime_r((time_t*)&atime, &x.atime);
localtime_r((time_t*)&ctime, &x.ctime);

View File

@ -25,6 +25,7 @@
#include <ctime>
#include "Common/File/FileUtil.h"
#include "Common/File/DirListing.h"
#include "Common/StringUtils.h"
#include "Common/Serialize/Serializer.h"
#include "Common/Serialize/SerializeFuncs.h"
@ -631,8 +632,8 @@ PSPFileInfo VirtualDiscFileSystem::GetFileInfo(std::string filename) {
}
if (x.type != FILETYPE_DIRECTORY) {
File::FileDetails details;
if (!File::GetFileDetails(fullName, &details)) {
File::FileInfo details;
if (!File::GetFileInfo(fullName.c_str(), &details)) {
ERROR_LOG(FILESYS, "DirectoryFileSystem::GetFileInfo: GetFileDetails failed: %s", fullName.c_str());
x.size = 0;
x.access = 0;

View File

@ -176,7 +176,7 @@ UI::EventReturn CwCheatScreen::OnEditCheatFile(UI::EventParams &params) {
#if PPSSPP_PLATFORM(UWP)
LaunchBrowser(engine_->CheatFilename().c_str());
#else
File::openIniFile(engine_->CheatFilename());
File::OpenFileInEditor(engine_->CheatFilename());
#endif
}
return UI::EVENT_DONE;

View File

@ -1733,7 +1733,7 @@ UI::EventReturn DeveloperToolsScreen::OnOpenTexturesIniFile(UI::EventParams &e)
std::string gameID = g_paramSFO.GetDiscID();
std::string generatedFilename;
if (TextureReplacer::GenerateIni(gameID, &generatedFilename)) {
File::openIniFile(generatedFilename);
File::OpenFileInEditor(generatedFilename);
}
return UI::EVENT_DONE;
}
@ -1785,7 +1785,6 @@ UI::EventReturn DeveloperToolsScreen::OnCopyStatesToRoot(UI::EventParams &e) {
return UI::EVENT_DONE;
}
UI::EventReturn DeveloperToolsScreen::OnRemoteDebugger(UI::EventParams &e) {
if (allowDebugger_) {
StartWebServer(WebServerFlags::DEBUGGER);