Skip to content

Commit

Permalink
Fix multiple issues preventing in-game saves from working.
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Jul 19, 2021
1 parent 2f04fc1 commit e73e0dc
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 29 deletions.
50 changes: 46 additions & 4 deletions Common/File/FileUtil.cpp
Expand Up @@ -155,32 +155,74 @@ FILE *OpenCFile(const Path &path, const char *mode) {
#endif
}

static std::string OpenFlagToString(OpenFlag flags) {
std::string s;
if (flags & OPEN_READ)
s += "READ|";
if (flags & OPEN_WRITE)
s += "WRITE|";
if (flags & OPEN_APPEND)
s += "APPEND|";
if (flags & OPEN_CREATE)
s += "CREATE|";
if (flags & OPEN_TRUNCATE)
s += "TRUNCATE|";
if (!s.empty()) {
s.pop_back(); // Remove trailing separator.
}
return s;
}

int OpenFD(const Path &path, OpenFlag flags) {
switch (path.Type()) {
case PathType::CONTENT_URI:
break;
default:
// Not yet supported.
ERROR_LOG(COMMON, "OpenFD: Only supports Content URI paths. Not '%s' (%s)!", path.c_str(), OpenFlagToString(flags).c_str());
// Not yet supported - use other paths.
return -1;
}

if (flags & OPEN_CREATE) {
if (!File::Exists(path)) {
INFO_LOG(COMMON, "OpenFD(%s): Creating file.", path.c_str());
std::string name = path.GetFilename();
if (path.CanNavigateUp()) {
Path parent = path.NavigateUp();
if (!Android_CreateFile(parent.ToString(), name)) {
WARN_LOG(COMMON, "OpenFD: Failed to create file '%s' in '%s'", name.c_str(), parent.c_str());
return -1;
}
} else {
INFO_LOG(COMMON, "Failed to navigate up to create file: %s", path.c_str());
return -1;
}
} else {
INFO_LOG(COMMON, "OpenCFile(%s): Opening existing content file ('%s')", path.c_str(), OpenFlagToString(flags).c_str());
}
}

Android_OpenContentUriMode mode;
if (flags == OPEN_READ) {
mode = Android_OpenContentUriMode::READ;
} else if (flags & OPEN_WRITE) {
if (flags & OPEN_TRUNCATE) {
mode = Android_OpenContentUriMode::READ_WRITE;
} else {
mode = Android_OpenContentUriMode::READ_WRITE_TRUNCATE;
} else {
mode = Android_OpenContentUriMode::READ_WRITE;
}
// TODO: Maybe better checking of additional flags here.
} else {
// TODO: Add support for more modes if possible.
ERROR_LOG_REPORT_ONCE(openFlagNotSupported, COMMON, "OpenFlag 0x%x not yet supported", flags);
ERROR_LOG_REPORT_ONCE(openFlagNotSupported, COMMON, "OpenFlag %s not yet supported", OpenFlagToString(flags).c_str());
return -1;
}

INFO_LOG(COMMON, "Android_OpenContentUriFd: %s (%s)", path.c_str(), OpenFlagToString(flags).c_str());
int descriptor = Android_OpenContentUriFd(path.ToString(), mode);
if (descriptor < 0) {
ERROR_LOG(COMMON, "Android_OpenContentUriFd failed: '%s'", path.c_str());
}
return descriptor;
}

Expand Down
4 changes: 2 additions & 2 deletions Core/Dialog/SavedataParam.cpp
Expand Up @@ -208,12 +208,12 @@ void SavedataParam::Init()
pspFileSystem.MkDir(savePath);
}
// Create a nomedia file to hide save icons form Android image viewer
#ifdef __ANDROID__
#if PPSSPP_PLATFORM(ANDROID)
int handle = pspFileSystem.OpenFile(savePath + ".nomedia", (FileAccess)(FILEACCESS_CREATE | FILEACCESS_WRITE), 0);
if (handle >= 0) {
pspFileSystem.CloseFile(handle);
} else {
ERROR_LOG(IO, "Failed to create .nomedia file");
INFO_LOG(IO, "Failed to create .nomedia file (might be ok if it already exists)");

This comment has been minimized.

Copy link
@unknownbrackets

unknownbrackets Jul 25, 2021

Collaborator

Ah hm, maybe we should do an exists check, at least around the error. Oh well.

-[Unknown]

}
#endif
}
Expand Down
47 changes: 28 additions & 19 deletions Core/FileSystems/DirectoryFileSystem.cpp
Expand Up @@ -67,8 +67,7 @@
#endif

#if HOST_IS_CASE_SENSITIVE
static bool FixFilenameCase(const std::string &path, std::string &filename)
{
static bool FixFilenameCase(const std::string &path, std::string &filename) {
// Are we lucky?
if (File::Exists(Path(path + filename)))
return true;
Expand Down Expand Up @@ -112,8 +111,14 @@ static bool FixFilenameCase(const std::string &path, std::string &filename)
return retValue;
}

bool FixPathCase(const std::string &basePath, std::string &path, FixPathCaseBehavior behavior)
{
bool FixPathCase(const Path &realBasePath, std::string &path, FixPathCaseBehavior behavior) {
if (realBasePath.Type() == PathType::CONTENT_URI) {
// Nothing to do. These are already case insensitive, I think.
return true;
}

std::string basePath = realBasePath.ToString();

size_t len = path.size();

if (len == 0)
Expand Down Expand Up @@ -189,7 +194,7 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File
#if HOST_IS_CASE_SENSITIVE
if (access & (FILEACCESS_APPEND | FILEACCESS_CREATE | FILEACCESS_WRITE)) {
DEBUG_LOG(FILESYS, "Checking case for path %s", fileName.c_str());
if (!FixPathCase(basePath.ToString(), fileName, FPC_PATH_MUST_EXIST)) {
if (!FixPathCase(basePath, fileName, FPC_PATH_MUST_EXIST)) {
error = SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND;
return false; // or go on and attempt (for a better error code than just 0?)
}
Expand All @@ -198,7 +203,7 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File
#endif

Path fullName = GetLocalPath(basePath, fileName);
VERBOSE_LOG(FILESYS, "Actually opening %s", fullName.c_str());
INFO_LOG(FILESYS, "Actually opening %s", fullName.c_str());

// On the PSP, truncating doesn't lose data. If you seek later, you'll recover it.
// This is abnormal, so we deviate from the PSP's behavior and truncate on write/close.
Expand Down Expand Up @@ -289,13 +294,16 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File
// Success
return true;
} else {
ERROR_LOG(FILESYS, "File::OpenFD returned an error");
// TODO: Need better error codes from OpenFD so we can distinguish
// disk full. Just set not found for now.
error = SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND;
return false;
}
}

INFO_LOG(FILESYS, "Opening '%s' straight", fullName.c_str());

int flags = 0;
if (access & FILEACCESS_APPEND) {
flags |= O_APPEND;
Expand All @@ -320,7 +328,7 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File

#if HOST_IS_CASE_SENSITIVE
if (!success && !(access & FILEACCESS_CREATE)) {
if (!FixPathCase(basePath.ToString(), fileName, FPC_PATH_MUST_EXIST)) {
if (!FixPathCase(basePath, fileName, FPC_PATH_MUST_EXIST)) {
error = SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND;
return false;
}
Expand Down Expand Up @@ -520,7 +528,7 @@ bool DirectoryFileSystem::MkDir(const std::string &dirname) {
// duplicate (different case) directories

std::string fixedCase = dirname;
if (!FixPathCase(basePath.ToString(), fixedCase, FPC_PARTIAL_ALLOWED))
if (!FixPathCase(basePath, fixedCase, FPC_PARTIAL_ALLOWED))
result = false;
else
result = File::CreateFullPath(GetLocalPath(fixedCase));
Expand All @@ -540,7 +548,7 @@ bool DirectoryFileSystem::RmDir(const std::string &dirname) {

// Nope, fix case and try again. Should we try again?
std::string fullPath = dirname;
if (!FixPathCase(basePath.ToString(), fullPath, FPC_FILE_MUST_EXIST))
if (!FixPathCase(basePath, fullPath, FPC_FILE_MUST_EXIST))
return (bool)ReplayApplyDisk(ReplayAction::RMDIR, false, CoreTiming::GetGlobalTimeUs());

fullName = GetLocalPath(fullPath);
Expand Down Expand Up @@ -571,7 +579,7 @@ int DirectoryFileSystem::RenameFile(const std::string &from, const std::string &

#if HOST_IS_CASE_SENSITIVE
// In case TO should overwrite a file with different case. Check error code?
if (!FixPathCase(basePath.ToString(), fullTo, FPC_PATH_MUST_EXIST))
if (!FixPathCase(basePath, fullTo, FPC_PATH_MUST_EXIST))
return ReplayApplyDisk(ReplayAction::FILE_RENAME, -1, CoreTiming::GetGlobalTimeUs());
#endif

Expand All @@ -584,7 +592,7 @@ int DirectoryFileSystem::RenameFile(const std::string &from, const std::string &
{
// May have failed due to case sensitivity on FROM, so try again. Check error code?
std::string fullFromPath = from;
if (!FixPathCase(basePath.ToString(), fullFromPath, FPC_FILE_MUST_EXIST))
if (!FixPathCase(basePath, fullFromPath, FPC_FILE_MUST_EXIST))
return ReplayApplyDisk(ReplayAction::FILE_RENAME, -1, CoreTiming::GetGlobalTimeUs());
fullFrom = GetLocalPath(fullFromPath);

Expand All @@ -607,7 +615,7 @@ bool DirectoryFileSystem::RemoveFile(const std::string &filename) {
{
// May have failed due to case sensitivity, so try again. Try even if it fails?
std::string fullNamePath = filename;
if (!FixPathCase(basePath.ToString(), fullNamePath, FPC_FILE_MUST_EXIST))
if (!FixPathCase(basePath, fullNamePath, FPC_FILE_MUST_EXIST))
return (bool)ReplayApplyDisk(ReplayAction::FILE_REMOVE, false, CoreTiming::GetGlobalTimeUs());
localPath = GetLocalPath(fullNamePath);

Expand Down Expand Up @@ -739,7 +747,7 @@ PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) {
Path fullName = GetLocalPath(filename);
if (!File::Exists(fullName)) {
#if HOST_IS_CASE_SENSITIVE
if (! FixPathCase(basePath.ToString(), filename, FPC_FILE_MUST_EXIST))
if (! FixPathCase(basePath, filename, FPC_FILE_MUST_EXIST))
return ReplayApplyDiskFileInfo(x, CoreTiming::GetGlobalTimeUs());
fullName = GetLocalPath(filename);

Expand Down Expand Up @@ -852,13 +860,14 @@ std::vector<PSPFileInfo> DirectoryFileSystem::GetDirListing(std::string path) {
std::vector<PSPFileInfo> myVector;

std::vector<File::FileInfo> files;
if (!File::GetFilesInDir(GetLocalPath(path), &files, nullptr, 0)) {
Path localPath = GetLocalPath(path);
if (!File::GetFilesInDir(localPath, &files, nullptr, 0)) {
// TODO: Case sensitivity should be checked on a file system basis, right?
#if HOST_IS_CASE_SENSITIVE
if (FixPathCase(basePath.ToString(), path, FPC_FILE_MUST_EXIST)) {
if (FixPathCase(basePath, path, FPC_FILE_MUST_EXIST)) {
// May have failed due to case sensitivity, try again
localPath = GetLocalPath(path);
if (!File::GetFilesInDir(GetLocalPath(path), &files, nullptr, 0)) {
if (!File::GetFilesInDir(localPath, &files, nullptr, 0)) {
return ReplayApplyDiskListing(myVector, CoreTiming::GetGlobalTimeUs());
}
}
Expand Down Expand Up @@ -911,9 +920,9 @@ u64 DirectoryFileSystem::FreeSpace(const std::string &path) {

#if HOST_IS_CASE_SENSITIVE
std::string fixedCase = path;
if (FixPathCase(basePath.ToString(), fixedCase, FPC_FILE_MUST_EXIST)) {
if (FixPathCase(basePath, fixedCase, FPC_FILE_MUST_EXIST)) {
// May have failed due to case sensitivity, try again.
if (free_disk_space(GetLocalPath(fixedCase).ToString(), result)) {
if (free_disk_space(GetLocalPath(fixedCase), result)) {
return ReplayApplyDisk64(ReplayAction::FREESPACE, result, CoreTiming::GetGlobalTimeUs());
}
}
Expand Down Expand Up @@ -1022,7 +1031,7 @@ int VFSFileSystem::OpenFile(std::string filename, FileAccess access, const char

std::string fullName = GetLocalPath(filename);
const char *fullNameC = fullName.c_str();
VERBOSE_LOG(FILESYS,"VFSFileSystem actually opening %s (%s)", fullNameC, filename.c_str());
VERBOSE_LOG(FILESYS, "VFSFileSystem actually opening %s (%s)", fullNameC, filename.c_str());

size_t size;
u8 *data = VFSReadFile(fullNameC, &size);
Expand Down
2 changes: 1 addition & 1 deletion Core/FileSystems/DirectoryFileSystem.h
Expand Up @@ -55,7 +55,7 @@ enum FixPathCaseBehavior {
FPC_PARTIAL_ALLOWED, // don't care how many exist (mkdir recursive)
};

bool FixPathCase(const std::string &basePath, std::string &path, FixPathCaseBehavior behavior);
bool FixPathCase(const Path &basePath, std::string &path, FixPathCaseBehavior behavior);
#endif

struct DirectoryFileHandle {
Expand Down
9 changes: 6 additions & 3 deletions Core/FileSystems/VirtualDiscFileSystem.cpp
Expand Up @@ -274,7 +274,7 @@ int VirtualDiscFileSystem::getFileListIndex(std::string &fileName)
Path fullName = GetLocalPath(fileName);
if (! File::Exists(fullName)) {
#if HOST_IS_CASE_SENSITIVE
if (! FixPathCase(basePath.ToString(), fileName, FPC_FILE_MUST_EXIST))
if (! FixPathCase(basePath, fileName, FPC_FILE_MUST_EXIST))
return -1;
fullName = GetLocalPath(fileName);

Expand Down Expand Up @@ -602,7 +602,7 @@ PSPFileInfo VirtualDiscFileSystem::GetFileInfo(std::string filename) {
Path fullName = GetLocalPath(filename);
if (!File::Exists(fullName)) {
#if HOST_IS_CASE_SENSITIVE
if (! FixPathCase(basePath.ToString(), filename, FPC_FILE_MUST_EXIST))
if (! FixPathCase(basePath, filename, FPC_FILE_MUST_EXIST))
return x;
fullName = GetLocalPath(filename);

Expand Down Expand Up @@ -661,6 +661,9 @@ static void tmFromFiletime(tm &dest, FILETIME &src)
std::vector<PSPFileInfo> VirtualDiscFileSystem::GetDirListing(std::string path)
{
std::vector<PSPFileInfo> myVector;

// TODO(scoped): Switch this over to GetFilesInDir!

#ifdef _WIN32
WIN32_FIND_DATA findData;
HANDLE hFind;
Expand Down Expand Up @@ -708,7 +711,7 @@ std::vector<PSPFileInfo> VirtualDiscFileSystem::GetDirListing(std::string path)
DIR *dp = opendir(localPath.c_str());

#if HOST_IS_CASE_SENSITIVE
if(dp == NULL && FixPathCase(basePath.ToString(), path, FPC_FILE_MUST_EXIST)) {
if(dp == NULL && FixPathCase(basePath, path, FPC_FILE_MUST_EXIST)) {
// May have failed due to case sensitivity, try again
localPath = GetLocalPath(path);
dp = opendir(localPath.c_str());
Expand Down

0 comments on commit e73e0dc

Please sign in to comment.