diff --git a/Common/File/FileUtil.cpp b/Common/File/FileUtil.cpp index 7d388bb13e..df4b3d3a8e 100644 --- a/Common/File/FileUtil.cpp +++ b/Common/File/FileUtil.cpp @@ -105,6 +105,8 @@ FILE *OpenCFile(const Path &path, const char *mode) { // Read, let's support this - easy one. int descriptor = Android_OpenContentUriFd(path.ToString(), Android_OpenContentUriMode::READ); if (descriptor == -1) { + // Set last error message? + // We're gonna need some error codes.. return nullptr; } return fdopen(descriptor, "rb"); @@ -125,6 +127,25 @@ FILE *OpenCFile(const Path &path, const char *mode) { #endif } +int OpenFD(const Path &path, OpenFlag flags) { + switch (path.Type()) { + case PathType::CONTENT_URI: + break; + default: + // Not yet supported. + return -1; + } + + if (flags != OPEN_READ) { + // TODO + ERROR_LOG(COMMON, "Modes other than plain OPEN_READ not yet supported"); + return -1; + } + + int descriptor = Android_OpenContentUriFd(path.ToString(), Android_OpenContentUriMode::READ); + return descriptor; +} + #ifdef _WIN32 static bool ResolvePathVista(const std::wstring &path, wchar_t *buf, DWORD bufSize) { typedef DWORD(WINAPI *getFinalPathNameByHandleW_f)(HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags); @@ -721,7 +742,7 @@ bool CreateEmptyFile(const Path &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()); + ERROR_LOG(COMMON, "CreateEmptyFile: failed to create '%s': %s", filename.c_str(), GetLastErrorMsg().c_str()); return false; } fclose(pFile); diff --git a/Common/File/FileUtil.h b/Common/File/FileUtil.h index 4ca7c7df21..ab0782fb22 100644 --- a/Common/File/FileUtil.h +++ b/Common/File/FileUtil.h @@ -42,6 +42,21 @@ namespace File { // Mostly to handle UTF-8 filenames better on Windows. FILE *OpenCFile(const Path &filename, const char *mode); +// Reminiscent of PSP's FileAccess enum, due to its use in emulating it. +enum OpenFlag { + OPEN_NONE = 0, + OPEN_READ = 1, + OPEN_WRITE = 2, + OPEN_APPEND = 4, + OPEN_CREATE = 8, + OPEN_TRUNCATE = 16, + // EXCL? +}; + +// TODO: This currently only handles Android Content URIs, but might port the rest +// of DirectoryFileSystem::Open here eventually for symmetry. +int OpenFD(const Path &filename, OpenFlag flags); + // Resolves symlinks and similar. std::string ResolvePath(const std::string &path); diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index d15c953408..d328c37d1b 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -187,7 +187,7 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File error = 0; #if HOST_IS_CASE_SENSITIVE - if (access & (FILEACCESS_APPEND|FILEACCESS_CREATE|FILEACCESS_WRITE)) { + 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)) { error = SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND; @@ -208,7 +208,7 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File } //TODO: tests, should append seek to end of file? seeking in a file opened for append? -#ifdef _WIN32 +#if PPSSPP_PLATFORM(WINDOWS) // Convert parameters to Windows permissions and access DWORD desired = 0; DWORD sharemode = 0; @@ -265,6 +265,29 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File } } #else + if (fullName.Type() == PathType::CONTENT_URI) { + // Convert flags. Don't want to share this type, bad dependency. + u32 flags = File::OPEN_NONE; + if (access & FILEACCESS_READ) + flags |= File::OPEN_READ; + if (access & FILEACCESS_WRITE) + flags |= File::OPEN_WRITE; + if (access & FILEACCESS_APPEND) + flags |= File::OPEN_APPEND; + if (access & FILEACCESS_CREATE) + flags |= File::OPEN_CREATE; + if (access & FILEACCESS_TRUNCATE) + flags |= File::OPEN_TRUNCATE; + + int fd = File::OpenFD(fullName, (File::OpenFlag)flags); + hFile = fd; + // Try to detect reads/writes to PSP/GAME to avoid them in replays. + if (fullName.FilePathContains("PSP/GAME/")) { + inGameDir_ = true; + } + return fd != -1; + } + int flags = 0; if (access & FILEACCESS_APPEND) { flags |= O_APPEND; @@ -623,18 +646,22 @@ int DirectoryFileSystem::OpenFile(std::string filename, FileAccess access, const err = ReplayApplyDisk(ReplayAction::FILE_OPEN, err, CoreTiming::GetGlobalTimeUs()); if (err != 0) { + std::string errorString; + int err; #ifdef _WIN32 auto win32err = GetLastError(); - ERROR_LOG(FILESYS, "DirectoryFileSystem::OpenFile: FAILED, %i - access = %i, %s", (int)win32err, (int)access, GetStringErrorMsg(win32err).c_str()); + err = (int)win32err; + errorString = GetStringErrorMsg(win32err); #else - ERROR_LOG(FILESYS, "DirectoryFileSystem::OpenFile: FAILED, %i - access = %i", errno, (int)access); + err = (int)errno; #endif - //wwwwaaaaahh!! + ERROR_LOG(FILESYS, "DirectoryFileSystem::OpenFile(%s): FAILED, %i - access = %d '%s'", filename.c_str(), err, (int)access, errorString.c_str()); return err; } else { #ifdef _WIN32 - if (access & FILEACCESS_APPEND) - entry.hFile.Seek(0,FILEMOVE_END); + if (access & FILEACCESS_APPEND) { + entry.hFile.Seek(0, FILEMOVE_END); + } #endif u32 newHandle = hAlloc->GetNewHandle();