summaryrefslogtreecommitdiffstats
path: root/src/core/file_sys
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2016-03-20 21:11:49 +0100
committerbunnei <bunneidev@gmail.com>2016-03-20 21:11:49 +0100
commitb83e95727f95fa6fe35d436be3e821605244a6a8 (patch)
tree64255c7432e882205a2dbea1fe962025863664ee /src/core/file_sys
parentMerge pull request #1550 from LittleWhite-tb/gdbstub_include_fix (diff)
parentHLE/FS: Change the error code returned when an ExtSaveData archive is not found. (diff)
downloadyuzu-b83e95727f95fa6fe35d436be3e821605244a6a8.tar
yuzu-b83e95727f95fa6fe35d436be3e821605244a6a8.tar.gz
yuzu-b83e95727f95fa6fe35d436be3e821605244a6a8.tar.bz2
yuzu-b83e95727f95fa6fe35d436be3e821605244a6a8.tar.lz
yuzu-b83e95727f95fa6fe35d436be3e821605244a6a8.tar.xz
yuzu-b83e95727f95fa6fe35d436be3e821605244a6a8.tar.zst
yuzu-b83e95727f95fa6fe35d436be3e821605244a6a8.zip
Diffstat (limited to 'src/core/file_sys')
-rw-r--r--src/core/file_sys/archive_backend.h29
-rw-r--r--src/core/file_sys/archive_extsavedata.cpp48
-rw-r--r--src/core/file_sys/archive_extsavedata.h12
-rw-r--r--src/core/file_sys/archive_romfs.cpp8
-rw-r--r--src/core/file_sys/archive_romfs.h3
-rw-r--r--src/core/file_sys/archive_savedata.cpp36
-rw-r--r--src/core/file_sys/archive_savedata.h4
-rw-r--r--src/core/file_sys/archive_savedatacheck.cpp8
-rw-r--r--src/core/file_sys/archive_savedatacheck.h3
-rw-r--r--src/core/file_sys/archive_sdmc.cpp7
-rw-r--r--src/core/file_sys/archive_sdmc.h3
-rw-r--r--src/core/file_sys/archive_systemsavedata.cpp8
-rw-r--r--src/core/file_sys/archive_systemsavedata.h3
-rw-r--r--src/core/file_sys/disk_archive.cpp80
-rw-r--r--src/core/file_sys/disk_archive.h12
-rw-r--r--src/core/file_sys/file_backend.h13
-rw-r--r--src/core/file_sys/ivfc_archive.cpp21
-rw-r--r--src/core/file_sys/ivfc_archive.h12
18 files changed, 236 insertions, 74 deletions
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h
index 601e95d8c..5d91e47f3 100644
--- a/src/core/file_sys/archive_backend.h
+++ b/src/core/file_sys/archive_backend.h
@@ -11,6 +11,7 @@
#include "common/bit_field.h"
#include "common/common_types.h"
+#include "common/swap.h"
#include "core/hle/result.h"
@@ -62,6 +63,14 @@ private:
std::u16string u16str;
};
+struct ArchiveFormatInfo {
+ u32_le total_size; ///< The pre-defined size of the archive, as specified in the Create or Format call
+ u32_le number_directories; ///< The pre-defined number of directories in the archive, as specified in the Create or Format call
+ u32_le number_files; ///< The pre-defined number of files in the archive, as specified in the Create or Format call
+ u8 duplicate_data; ///< Whether the archive should duplicate the data, as specified in the Create or Format call
+};
+static_assert(std::is_pod<ArchiveFormatInfo>::value, "ArchiveFormatInfo is not POD");
+
class ArchiveBackend : NonCopyable {
public:
virtual ~ArchiveBackend() {
@@ -76,16 +85,16 @@ public:
* Open a file specified by its path, using the specified mode
* @param path Path relative to the archive
* @param mode Mode to open the file with
- * @return Opened file, or nullptr
+ * @return Opened file, or error code
*/
- virtual std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const = 0;
+ virtual ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, const Mode mode) const = 0;
/**
* Delete a file specified by its path
* @param path Path relative to the archive
- * @return Whether the file could be deleted
+ * @return Result of the operation
*/
- virtual bool DeleteFile(const Path& path) const = 0;
+ virtual ResultCode DeleteFile(const Path& path) const = 0;
/**
* Rename a File specified by its path
@@ -108,7 +117,7 @@ public:
* @param size The size of the new file, filled with zeroes
* @return File creation result code
*/
- virtual ResultCode CreateFile(const Path& path, u32 size) const = 0;
+ virtual ResultCode CreateFile(const Path& path, u64 size) const = 0;
/**
* Create a directory specified by its path
@@ -159,9 +168,17 @@ public:
/**
* Deletes the archive contents and then re-creates the base folder
* @param path Path to the archive
+ * @param format_info Format information for the new archive
* @return ResultCode of the operation, 0 on success
*/
- virtual ResultCode Format(const Path& path) = 0;
+ virtual ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) = 0;
+
+ /**
+ * Retrieves the format info about the archive with the specified path
+ * @param path Path to the archive
+ * @return Format information about the archive or error code
+ */
+ virtual ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const = 0;
};
} // namespace FileSys
diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp
index 92dad8e6f..961264fe5 100644
--- a/src/core/file_sys/archive_extsavedata.cpp
+++ b/src/core/file_sys/archive_extsavedata.cpp
@@ -58,7 +58,7 @@ Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) {
}
ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location, bool shared)
- : mount_point(GetExtDataContainerPath(mount_location, shared)) {
+ : shared(shared), mount_point(GetExtDataContainerPath(mount_location, shared)) {
LOG_INFO(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str());
}
@@ -74,21 +74,59 @@ bool ArchiveFactory_ExtSaveData::Initialize() {
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(const Path& path) {
std::string fullpath = GetExtSaveDataPath(mount_point, path) + "user/";
if (!FileUtil::Exists(fullpath)) {
- // TODO(Subv): Check error code, this one is probably wrong
- return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
- ErrorSummary::InvalidState, ErrorLevel::Status);
+ // TODO(Subv): Verify the archive behavior of SharedExtSaveData compared to ExtSaveData.
+ // ExtSaveData seems to return FS_NotFound (120) when the archive doesn't exist.
+ if (!shared) {
+ return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS,
+ ErrorSummary::InvalidState, ErrorLevel::Status);
+ } else {
+ return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
+ ErrorSummary::InvalidState, ErrorLevel::Status);
+ }
}
auto archive = Common::make_unique<DiskArchive>(fullpath);
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
-ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path) {
+ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) {
// These folders are always created with the ExtSaveData
std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/";
std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/";
FileUtil::CreateFullPath(user_path);
FileUtil::CreateFullPath(boss_path);
+
+ // Write the format metadata
+ std::string metadata_path = GetExtSaveDataPath(mount_point, path) + "metadata";
+ FileUtil::IOFile file(metadata_path, "wb");
+
+ if (!file.IsOpen()) {
+ // TODO(Subv): Find the correct error code
+ return ResultCode(-1);
+ }
+
+ file.WriteBytes(&format_info, sizeof(format_info));
return RESULT_SUCCESS;
}
+ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Path& path) const {
+ std::string metadata_path = GetExtSaveDataPath(mount_point, path) + "metadata";
+ FileUtil::IOFile file(metadata_path, "rb");
+
+ if (!file.IsOpen()) {
+ LOG_ERROR(Service_FS, "Could not open metadata information for archive");
+ // TODO(Subv): Verify error code
+ return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status);
+ }
+
+ ArchiveFormatInfo info = {};
+ file.ReadBytes(&info, sizeof(info));
+ return MakeResult<ArchiveFormatInfo>(info);
+}
+
+void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, const u8* icon_data, size_t icon_size) {
+ std::string game_path = FileSys::GetExtSaveDataPath(GetMountPoint(), path);
+ FileUtil::IOFile icon_file(game_path + "icon", "wb");
+ icon_file.WriteBytes(icon_data, icon_size);
+}
+
} // namespace FileSys
diff --git a/src/core/file_sys/archive_extsavedata.h b/src/core/file_sys/archive_extsavedata.h
index ec8d770fc..287a6fee1 100644
--- a/src/core/file_sys/archive_extsavedata.h
+++ b/src/core/file_sys/archive_extsavedata.h
@@ -31,10 +31,19 @@ public:
std::string GetName() const override { return "ExtSaveData"; }
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
- ResultCode Format(const Path& path) override;
+ ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
+ ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
const std::string& GetMountPoint() const { return mount_point; }
+ /**
+ * Writes the SMDH icon of the ExtSaveData to file
+ * @param path Path of this ExtSaveData
+ * @param icon_data Binary data of the icon
+ * @param icon_size Size of the icon data
+ */
+ void WriteIcon(const Path& path, const u8* icon_data, size_t icon_size);
+
private:
/**
* This holds the full directory path for this archive, it is only set after a successful call
@@ -42,6 +51,7 @@ private:
* See GetExtSaveDataPath for the code that extracts this data from an archive path.
*/
std::string mount_point;
+ bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData archive
};
/**
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp
index 696b51a94..a9a29ebde 100644
--- a/src/core/file_sys/archive_romfs.cpp
+++ b/src/core/file_sys/archive_romfs.cpp
@@ -29,11 +29,17 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_RomFS::Open(const Path
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
-ResultCode ArchiveFactory_RomFS::Format(const Path& path) {
+ResultCode ArchiveFactory_RomFS::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) {
LOG_ERROR(Service_FS, "Attempted to format a RomFS archive.");
// TODO: Verify error code
return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS,
ErrorSummary::NotSupported, ErrorLevel::Permanent);
}
+ResultVal<ArchiveFormatInfo> ArchiveFactory_RomFS::GetFormatInfo(const Path& path) const {
+ // TODO(Subv): Implement
+ LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str());
+ return ResultCode(-1);
+}
+
} // namespace FileSys
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h
index 2bedfa9c6..c5a329122 100644
--- a/src/core/file_sys/archive_romfs.h
+++ b/src/core/file_sys/archive_romfs.h
@@ -26,7 +26,8 @@ public:
std::string GetName() const override { return "RomFS"; }
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
- ResultCode Format(const Path& path) override;
+ ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
+ ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
private:
std::shared_ptr<FileUtil::IOFile> romfs_file;
diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp
index 12876899f..fe020d21c 100644
--- a/src/core/file_sys/archive_savedata.cpp
+++ b/src/core/file_sys/archive_savedata.cpp
@@ -26,11 +26,17 @@ static std::string GetSaveDataContainerPath(const std::string& sdmc_directory) {
}
static std::string GetSaveDataPath(const std::string& mount_location, u64 program_id) {
- u32 high = program_id >> 32;
- u32 low = program_id & 0xFFFFFFFF;
+ u32 high = (u32)(program_id >> 32);
+ u32 low = (u32)(program_id & 0xFFFFFFFF);
return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, low);
}
+static std::string GetSaveDataMetadataPath(const std::string& mount_location, u64 program_id) {
+ u32 high = (u32)(program_id >> 32);
+ u32 low = (u32)(program_id & 0xFFFFFFFF);
+ return Common::StringFromFormat("%s%08x/%08x/data/00000001.metadata", mount_location.c_str(), high, low);
+}
+
ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directory)
: mount_point(GetSaveDataContainerPath(sdmc_directory)) {
LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str());
@@ -51,11 +57,35 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const P
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
-ResultCode ArchiveFactory_SaveData::Format(const Path& path) {
+ResultCode ArchiveFactory_SaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) {
std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id);
FileUtil::DeleteDirRecursively(concrete_mount_point);
FileUtil::CreateFullPath(concrete_mount_point);
+
+ // Write the format metadata
+ std::string metadata_path = GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id);
+ FileUtil::IOFile file(metadata_path, "wb");
+
+ if (file.IsOpen()) {
+ file.WriteBytes(&format_info, sizeof(format_info));
+ return RESULT_SUCCESS;
+ }
return RESULT_SUCCESS;
}
+ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path) const {
+ std::string metadata_path = GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id);
+ FileUtil::IOFile file(metadata_path, "rb");
+
+ if (!file.IsOpen()) {
+ LOG_ERROR(Service_FS, "Could not open metadata information for archive");
+ // TODO(Subv): Verify error code
+ return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status);
+ }
+
+ ArchiveFormatInfo info = {};
+ file.ReadBytes(&info, sizeof(info));
+ return MakeResult<ArchiveFormatInfo>(info);
+}
+
} // namespace FileSys
diff --git a/src/core/file_sys/archive_savedata.h b/src/core/file_sys/archive_savedata.h
index 1f65297dd..7a5a24089 100644
--- a/src/core/file_sys/archive_savedata.h
+++ b/src/core/file_sys/archive_savedata.h
@@ -23,7 +23,9 @@ public:
std::string GetName() const override { return "SaveData"; }
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
- ResultCode Format(const Path& path) override;
+ ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
+
+ ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
private:
std::string mount_point;
diff --git a/src/core/file_sys/archive_savedatacheck.cpp b/src/core/file_sys/archive_savedatacheck.cpp
index ea1dfe2c7..3db11c500 100644
--- a/src/core/file_sys/archive_savedatacheck.cpp
+++ b/src/core/file_sys/archive_savedatacheck.cpp
@@ -48,11 +48,17 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(co
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
-ResultCode ArchiveFactory_SaveDataCheck::Format(const Path& path) {
+ResultCode ArchiveFactory_SaveDataCheck::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) {
LOG_ERROR(Service_FS, "Attempted to format a SaveDataCheck archive.");
// TODO: Verify error code
return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS,
ErrorSummary::NotSupported, ErrorLevel::Permanent);
}
+ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveDataCheck::GetFormatInfo(const Path& path) const {
+ // TODO(Subv): Implement
+ LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str());
+ return ResultCode(-1);
+}
+
} // namespace FileSys
diff --git a/src/core/file_sys/archive_savedatacheck.h b/src/core/file_sys/archive_savedatacheck.h
index b14aefe8b..ea2624d64 100644
--- a/src/core/file_sys/archive_savedatacheck.h
+++ b/src/core/file_sys/archive_savedatacheck.h
@@ -23,7 +23,8 @@ public:
std::string GetName() const override { return "SaveDataCheck"; }
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
- ResultCode Format(const Path& path) override;
+ ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
+ ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
private:
std::string mount_point;
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp
index 5c825f429..657221cbf 100644
--- a/src/core/file_sys/archive_sdmc.cpp
+++ b/src/core/file_sys/archive_sdmc.cpp
@@ -40,9 +40,14 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path&
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
-ResultCode ArchiveFactory_SDMC::Format(const Path& path) {
+ResultCode ArchiveFactory_SDMC::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) {
// This is kind of an undesirable operation, so let's just ignore it. :)
return RESULT_SUCCESS;
}
+ResultVal<ArchiveFormatInfo> ArchiveFactory_SDMC::GetFormatInfo(const Path& path) const {
+ // TODO(Subv): Implement
+ LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str());
+ return ResultCode(-1);
+}
} // namespace FileSys
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h
index 10b273bdb..35c0f3725 100644
--- a/src/core/file_sys/archive_sdmc.h
+++ b/src/core/file_sys/archive_sdmc.h
@@ -29,7 +29,8 @@ public:
std::string GetName() const override { return "SDMC"; }
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
- ResultCode Format(const Path& path) override;
+ ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
+ ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
private:
std::string sdmc_directory;
diff --git a/src/core/file_sys/archive_systemsavedata.cpp b/src/core/file_sys/archive_systemsavedata.cpp
index 896f89529..e1780de2f 100644
--- a/src/core/file_sys/archive_systemsavedata.cpp
+++ b/src/core/file_sys/archive_systemsavedata.cpp
@@ -63,11 +63,17 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(c
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
-ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path) {
+ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) {
std::string fullpath = GetSystemSaveDataPath(base_path, path);
FileUtil::DeleteDirRecursively(fullpath);
FileUtil::CreateFullPath(fullpath);
return RESULT_SUCCESS;
}
+ResultVal<ArchiveFormatInfo> ArchiveFactory_SystemSaveData::GetFormatInfo(const Path& path) const {
+ // TODO(Subv): Implement
+ LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str());
+ return ResultCode(-1);
+}
+
} // namespace FileSys
diff --git a/src/core/file_sys/archive_systemsavedata.h b/src/core/file_sys/archive_systemsavedata.h
index afc689848..2bc13d4ee 100644
--- a/src/core/file_sys/archive_systemsavedata.h
+++ b/src/core/file_sys/archive_systemsavedata.h
@@ -23,7 +23,8 @@ public:
ArchiveFactory_SystemSaveData(const std::string& mount_point);
ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
- ResultCode Format(const Path& path) override;
+ ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
+ ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
std::string GetName() const override { return "SystemSaveData"; }
diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp
index a51416774..8e4ea01c5 100644
--- a/src/core/file_sys/disk_archive.cpp
+++ b/src/core/file_sys/disk_archive.cpp
@@ -17,16 +17,28 @@
namespace FileSys {
-std::unique_ptr<FileBackend> DiskArchive::OpenFile(const Path& path, const Mode mode) const {
+ResultVal<std::unique_ptr<FileBackend>> DiskArchive::OpenFile(const Path& path, const Mode mode) const {
LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex);
auto file = Common::make_unique<DiskFile>(*this, path, mode);
- if (!file->Open())
- return nullptr;
- return std::move(file);
+ ResultCode result = file->Open();
+ if (result.IsError())
+ return result;
+ return MakeResult<std::unique_ptr<FileBackend>>(std::move(file));
}
-bool DiskArchive::DeleteFile(const Path& path) const {
- return FileUtil::Delete(mount_point + path.AsString());
+ResultCode DiskArchive::DeleteFile(const Path& path) const {
+ std::string file_path = mount_point + path.AsString();
+
+ if (FileUtil::IsDirectory(file_path))
+ return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status);
+
+ if (!FileUtil::Exists(file_path))
+ return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Status);
+
+ if (FileUtil::Delete(file_path))
+ return RESULT_SUCCESS;
+
+ return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status);
}
bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const {
@@ -37,11 +49,14 @@ bool DiskArchive::DeleteDirectory(const Path& path) const {
return FileUtil::DeleteDir(mount_point + path.AsString());
}
-ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u32 size) const {
+ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u64 size) const {
std::string full_path = mount_point + path.AsString();
+ if (FileUtil::IsDirectory(full_path))
+ return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status);
+
if (FileUtil::Exists(full_path))
- return ResultCode(ErrorDescription::AlreadyExists, ErrorModule::FS, ErrorSummary::NothingHappened, ErrorLevel::Info);
+ return ResultCode(ErrorDescription::FS_AlreadyExists, ErrorModule::FS, ErrorSummary::NothingHappened, ErrorLevel::Status);
if (size == 0) {
FileUtil::CreateEmptyFile(full_path);
@@ -89,38 +104,57 @@ DiskFile::DiskFile(const DiskArchive& archive, const Path& path, const Mode mode
this->mode.hex = mode.hex;
}
-bool DiskFile::Open() {
- if (!mode.create_flag && !FileUtil::Exists(path)) {
- LOG_ERROR(Service_FS, "Non-existing file %s can't be open without mode create.", path.c_str());
- return false;
+ResultCode DiskFile::Open() {
+ if (FileUtil::IsDirectory(path))
+ return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status);
+
+ // Specifying only the Create flag is invalid
+ if (mode.create_flag && !mode.read_flag && !mode.write_flag) {
+ return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status);
+ }
+
+ if (!FileUtil::Exists(path)) {
+ if (!mode.create_flag) {
+ LOG_ERROR(Service_FS, "Non-existing file %s can't be open without mode create.", path.c_str());
+ return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Status);
+ } else {
+ // Create the file
+ FileUtil::CreateEmptyFile(path);
+ }
}
- std::string mode_string;
- if (mode.create_flag)
- mode_string = "w+";
- else if (mode.write_flag)
- mode_string = "r+"; // Files opened with Write access can be read from
+ std::string mode_string = "";
+ if (mode.write_flag)
+ mode_string += "r+"; // Files opened with Write access can be read from
else if (mode.read_flag)
- mode_string = "r";
+ mode_string += "r";
// Open the file in binary mode, to avoid problems with CR/LF on Windows systems
mode_string += "b";
file = Common::make_unique<FileUtil::IOFile>(path, mode_string.c_str());
- return file->IsOpen();
+ if (file->IsOpen())
+ return RESULT_SUCCESS;
+ return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Status);
}
-size_t DiskFile::Read(const u64 offset, const size_t length, u8* buffer) const {
+ResultVal<size_t> DiskFile::Read(const u64 offset, const size_t length, u8* buffer) const {
+ if (!mode.read_flag && !mode.write_flag)
+ return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status);
+
file->Seek(offset, SEEK_SET);
- return file->ReadBytes(buffer, length);
+ return MakeResult<size_t>(file->ReadBytes(buffer, length));
}
-size_t DiskFile::Write(const u64 offset, const size_t length, const bool flush, const u8* buffer) const {
+ResultVal<size_t> DiskFile::Write(const u64 offset, const size_t length, const bool flush, const u8* buffer) const {
+ if (!mode.write_flag)
+ return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status);
+
file->Seek(offset, SEEK_SET);
size_t written = file->WriteBytes(buffer, length);
if (flush)
file->Flush();
- return written;
+ return MakeResult<size_t>(written);
}
u64 DiskFile::GetSize() const {
diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h
index ef9a98057..b4cc2f702 100644
--- a/src/core/file_sys/disk_archive.h
+++ b/src/core/file_sys/disk_archive.h
@@ -33,11 +33,11 @@ public:
virtual std::string GetName() const override { return "DiskArchive: " + mount_point; }
- std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override;
- bool DeleteFile(const Path& path) const override;
+ ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, const Mode mode) const override;
+ ResultCode DeleteFile(const Path& path) const override;
bool RenameFile(const Path& src_path, const Path& dest_path) const override;
bool DeleteDirectory(const Path& path) const override;
- ResultCode CreateFile(const Path& path, u32 size) const override;
+ ResultCode CreateFile(const Path& path, u64 size) const override;
bool CreateDirectory(const Path& path) const override;
bool RenameDirectory(const Path& src_path, const Path& dest_path) const override;
std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override;
@@ -54,9 +54,9 @@ class DiskFile : public FileBackend {
public:
DiskFile(const DiskArchive& archive, const Path& path, const Mode mode);
- bool Open() override;
- size_t Read(u64 offset, size_t length, u8* buffer) const override;
- size_t Write(u64 offset, size_t length, bool flush, const u8* buffer) const override;
+ ResultCode Open() override;
+ ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const override;
+ ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const override;
u64 GetSize() const override;
bool SetSize(u64 size) const override;
bool Close() const override;
diff --git a/src/core/file_sys/file_backend.h b/src/core/file_sys/file_backend.h
index df7165df3..9137bbbad 100644
--- a/src/core/file_sys/file_backend.h
+++ b/src/core/file_sys/file_backend.h
@@ -7,6 +7,7 @@
#include <cstddef>
#include "common/common_types.h"
+#include "core/hle/result.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// FileSys namespace
@@ -20,18 +21,18 @@ public:
/**
* Open the file
- * @return true if the file opened correctly
+ * @return Result of the file operation
*/
- virtual bool Open() = 0;
+ virtual ResultCode Open() = 0;
/**
* Read data from the file
* @param offset Offset in bytes to start reading data from
* @param length Length in bytes of data to read from file
* @param buffer Buffer to read data into
- * @return Number of bytes read
+ * @return Number of bytes read, or error code
*/
- virtual size_t Read(u64 offset, size_t length, u8* buffer) const = 0;
+ virtual ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const = 0;
/**
* Write data to the file
@@ -39,9 +40,9 @@ public:
* @param length Length in bytes of data to write to file
* @param flush The flush parameters (0 == do not flush)
* @param buffer Buffer to read data from
- * @return Number of bytes written
+ * @return Number of bytes written, or error code
*/
- virtual size_t Write(u64 offset, size_t length, bool flush, const u8* buffer) const = 0;
+ virtual ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const = 0;
/**
* Get the size of the file in bytes
diff --git a/src/core/file_sys/ivfc_archive.cpp b/src/core/file_sys/ivfc_archive.cpp
index 2efc31a8c..a8e9a72ef 100644
--- a/src/core/file_sys/ivfc_archive.cpp
+++ b/src/core/file_sys/ivfc_archive.cpp
@@ -20,13 +20,15 @@ std::string IVFCArchive::GetName() const {
return "IVFC";
}
-std::unique_ptr<FileBackend> IVFCArchive::OpenFile(const Path& path, const Mode mode) const {
- return Common::make_unique<IVFCFile>(romfs_file, data_offset, data_size);
+ResultVal<std::unique_ptr<FileBackend>> IVFCArchive::OpenFile(const Path& path, const Mode mode) const {
+ return MakeResult<std::unique_ptr<FileBackend>>(Common::make_unique<IVFCFile>(romfs_file, data_offset, data_size));
}
-bool IVFCArchive::DeleteFile(const Path& path) const {
+ResultCode IVFCArchive::DeleteFile(const Path& path) const {
LOG_CRITICAL(Service_FS, "Attempted to delete a file from an IVFC archive (%s).", GetName().c_str());
- return false;
+ // TODO(Subv): Verify error code
+ return ResultCode(ErrorDescription::NoData, ErrorModule::FS,
+ ErrorSummary::Canceled, ErrorLevel::Status);
}
bool IVFCArchive::RenameFile(const Path& src_path, const Path& dest_path) const {
@@ -39,7 +41,7 @@ bool IVFCArchive::DeleteDirectory(const Path& path) const {
return false;
}
-ResultCode IVFCArchive::CreateFile(const Path& path, u32 size) const {
+ResultCode IVFCArchive::CreateFile(const Path& path, u64 size) const {
LOG_CRITICAL(Service_FS, "Attempted to create a file in an IVFC archive (%s).", GetName().c_str());
// TODO: Verify error code
return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent);
@@ -66,17 +68,18 @@ u64 IVFCArchive::GetFreeBytes() const {
////////////////////////////////////////////////////////////////////////////////////////////////////
-size_t IVFCFile::Read(const u64 offset, const size_t length, u8* buffer) const {
+ResultVal<size_t> IVFCFile::Read(const u64 offset, const size_t length, u8* buffer) const {
LOG_TRACE(Service_FS, "called offset=%llu, length=%zu", offset, length);
romfs_file->Seek(data_offset + offset, SEEK_SET);
size_t read_length = (size_t)std::min((u64)length, data_size - offset);
- return romfs_file->ReadBytes(buffer, read_length);
+ return MakeResult<size_t>(romfs_file->ReadBytes(buffer, read_length));
}
-size_t IVFCFile::Write(const u64 offset, const size_t length, const bool flush, const u8* buffer) const {
+ResultVal<size_t> IVFCFile::Write(const u64 offset, const size_t length, const bool flush, const u8* buffer) const {
LOG_ERROR(Service_FS, "Attempted to write to IVFC file");
- return 0;
+ // TODO(Subv): Find error code
+ return MakeResult<size_t>(0);
}
u64 IVFCFile::GetSize() const {
diff --git a/src/core/file_sys/ivfc_archive.h b/src/core/file_sys/ivfc_archive.h
index f3fd82de4..19d32dcca 100644
--- a/src/core/file_sys/ivfc_archive.h
+++ b/src/core/file_sys/ivfc_archive.h
@@ -34,11 +34,11 @@ public:
std::string GetName() const override;
- std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override;
- bool DeleteFile(const Path& path) const override;
+ ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, const Mode mode) const override;
+ ResultCode DeleteFile(const Path& path) const override;
bool RenameFile(const Path& src_path, const Path& dest_path) const override;
bool DeleteDirectory(const Path& path) const override;
- ResultCode CreateFile(const Path& path, u32 size) const override;
+ ResultCode CreateFile(const Path& path, u64 size) const override;
bool CreateDirectory(const Path& path) const override;
bool RenameDirectory(const Path& src_path, const Path& dest_path) const override;
std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override;
@@ -55,9 +55,9 @@ public:
IVFCFile(std::shared_ptr<FileUtil::IOFile> file, u64 offset, u64 size)
: romfs_file(file), data_offset(offset), data_size(size) {}
- bool Open() override { return true; }
- size_t Read(u64 offset, size_t length, u8* buffer) const override;
- size_t Write(u64 offset, size_t length, bool flush, const u8* buffer) const override;
+ ResultCode Open() override { return RESULT_SUCCESS; }
+ ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const override;
+ ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const override;
u64 GetSize() const override;
bool SetSize(u64 size) const override;
bool Close() const override { return false; }