diff --git a/app/src/main/cpp/skyline/loader/nca.cpp b/app/src/main/cpp/skyline/loader/nca.cpp index bbffef15..7452adc9 100644 --- a/app/src/main/cpp/skyline/loader/nca.cpp +++ b/app/src/main/cpp/skyline/loader/nca.cpp @@ -16,10 +16,11 @@ namespace skyline::loader { if (exeFs == nullptr) throw exception("Cannot load a null ExeFS"); - auto nsoFile{exeFs->OpenFile("rtld")}; - if (nsoFile == nullptr) + if (!exeFs->FileExists("rtld")) throw exception("Cannot load an ExeFS that doesn't contain rtld"); + auto nsoFile{exeFs->OpenFile("rtld")}; + state.process->memory.InitializeVmm(process->npdm.meta.flags.type); auto loadInfo{NsoLoader::LoadNso(loader, nsoFile, process, state, 0, "rtld.nso")}; diff --git a/app/src/main/cpp/skyline/loader/nsp.cpp b/app/src/main/cpp/skyline/loader/nsp.cpp index 77d18e8c..1a8527f8 100644 --- a/app/src/main/cpp/skyline/loader/nsp.cpp +++ b/app/src/main/cpp/skyline/loader/nsp.cpp @@ -50,7 +50,7 @@ namespace skyline::loader { // Use the first icon file available for (const auto &entry : root->Read()) { if (entry.name.rfind("icon") == 0) { - icon = controlRomFs->OpenFile(entry.name); + icon = controlRomFs->OpenFileUnchecked(entry.name); break; } } diff --git a/app/src/main/cpp/skyline/services/fssrv/IFile.cpp b/app/src/main/cpp/skyline/services/fssrv/IFile.cpp index 96c89df5..68c582c2 100644 --- a/app/src/main/cpp/skyline/services/fssrv/IFile.cpp +++ b/app/src/main/cpp/skyline/services/fssrv/IFile.cpp @@ -23,7 +23,7 @@ namespace skyline::service::fssrv { return result::InvalidSize; } - response.Push(static_cast(backing->Read(request.outputBuf.at(0), offset))); + response.Push(static_cast(backing->ReadUnchecked(request.outputBuf.at(0), offset))); return {}; } diff --git a/app/src/main/cpp/skyline/services/fssrv/IFileSystem.cpp b/app/src/main/cpp/skyline/services/fssrv/IFileSystem.cpp index 2b8fa0c9..4dec4119 100644 --- a/app/src/main/cpp/skyline/services/fssrv/IFileSystem.cpp +++ b/app/src/main/cpp/skyline/services/fssrv/IFileSystem.cpp @@ -38,7 +38,7 @@ namespace skyline::service::fssrv { if (!backing->FileExists(path)) return result::PathDoesNotExist; - auto file{backing->OpenFile(path, mode)}; + auto file{backing->OpenFileUnchecked(path, mode)}; if (file == nullptr) return result::UnexpectedFailure; else diff --git a/app/src/main/cpp/skyline/vfs/backing.h b/app/src/main/cpp/skyline/vfs/backing.h index 2d9f0e09..71be351a 100644 --- a/app/src/main/cpp/skyline/vfs/backing.h +++ b/app/src/main/cpp/skyline/vfs/backing.h @@ -53,14 +53,30 @@ namespace skyline::vfs { * @param offset The offset to start reading from * @return The amount of bytes read */ - size_t Read(span output, size_t offset = 0) { + size_t ReadUnchecked(span output, size_t offset = 0) { if (!mode.read) throw exception("Attempting to read a backing that is not readable"); - if ((static_cast(size) - offset) < output.size()) + return ReadImpl(output, offset); + }; + + /** + * @brief Read bytes from the backing at a particular offset to a buffer and check to ensure the full size was read + * @param output The object to write the data read to + * @param offset The offset to start reading from + * @return The amount of bytes read + */ + size_t Read(span output, size_t offset = 0) { + if (offset > size) + throw exception("Offset cannot be past the end of a backing"); + + if ((size - offset) < output.size()) throw exception("Trying to read past the end of a backing: 0x{:X}/0x{:X} (Offset: 0x{:X})", output.size(), size, offset); - return ReadImpl(output, offset); + if (ReadUnchecked(output, offset) != size) + throw exception("Failed to read the requested size from backing"); + + return size; }; /** diff --git a/app/src/main/cpp/skyline/vfs/ctr_encrypted_backing.cpp b/app/src/main/cpp/skyline/vfs/ctr_encrypted_backing.cpp index e539d7b9..d36f946a 100644 --- a/app/src/main/cpp/skyline/vfs/ctr_encrypted_backing.cpp +++ b/app/src/main/cpp/skyline/vfs/ctr_encrypted_backing.cpp @@ -25,7 +25,7 @@ namespace skyline::vfs { size_t sectorOffset{offset % SectorSize}; if (sectorOffset == 0) { - size_t read{backing->Read(output, offset)}; + size_t read{backing->ReadUnchecked(output, offset)}; if (read != size) return 0; { @@ -38,7 +38,7 @@ namespace skyline::vfs { size_t sectorStart{offset - sectorOffset}; std::vector blockBuf(SectorSize); - size_t read{backing->Read(blockBuf, sectorStart)}; + size_t read{backing->ReadUnchecked(blockBuf, sectorStart)}; if (read != SectorSize) return 0; { @@ -53,6 +53,6 @@ namespace skyline::vfs { size_t readInBlock{SectorSize - sectorOffset}; std::memcpy(output.data(), blockBuf.data() + sectorOffset, readInBlock); - return readInBlock + Read(output.subspan(readInBlock), offset + readInBlock); + return readInBlock + ReadUnchecked(output.subspan(readInBlock), offset + readInBlock); } } diff --git a/app/src/main/cpp/skyline/vfs/filesystem.h b/app/src/main/cpp/skyline/vfs/filesystem.h index 3d6d66e7..53e80068 100644 --- a/app/src/main/cpp/skyline/vfs/filesystem.h +++ b/app/src/main/cpp/skyline/vfs/filesystem.h @@ -62,15 +62,29 @@ namespace skyline::vfs { * @brief Opens a file from the specified path in the filesystem * @param path The path to the file * @param mode The mode to open the file with - * @return A shared pointer to a Backing object of the file + * @return A shared pointer to a Backing object of the file (may be nullptr) */ - std::shared_ptr OpenFile(const std::string &path, Backing::Mode mode = {true, false, false}) { + std::shared_ptr OpenFileUnchecked(const std::string &path, Backing::Mode mode = {true, false, false}) { if (!mode.write && !mode.read) throw exception("Cannot open a file with a mode that is neither readable nor writable"); return OpenFileImpl(path, mode); } + /** + * @brief Opens a file from the specified path in the filesystem and throws an exception if opening fails + * @param path The path to the file + * @param mode The mode to open the file with + * @return A shared pointer to a Backing object of the file + */ + std::shared_ptr OpenFile(const std::string &path, Backing::Mode mode = {true, false, false}) { + auto file{OpenFileUnchecked(path, mode)}; + if (file == nullptr) + throw exception("Failed to open file: {}", path); + + return file; + } + /** * @brief Queries the type of the entry given by path * @param path The path to the entry @@ -104,13 +118,27 @@ namespace skyline::vfs { * @brief Opens a directory from the specified path in the filesystem * @param path The path to the directory * @param listMode The list mode for the directory - * @return A shared pointer to a Directory object of the directory + * @return A shared pointer to a Directory object of the directory (may be nullptr) */ - std::shared_ptr OpenDirectory(const std::string &path, Directory::ListMode listMode = {true, true}) { + std::shared_ptr OpenDirectoryUnchecked(const std::string &path, Directory::ListMode listMode = {true, true}) { if (!listMode.raw) throw exception("Cannot open a directory with an empty listMode"); return OpenDirectoryImpl(path, listMode); }; + + /** + * @brief Opens a directory from the specified path in the filesystem and throws an exception if opening fails + * @param path The path to the directory + * @param listMode The list mode for the directory + * @return A shared pointer to a Directory object of the directory + */ + std::shared_ptr OpenDirectory(const std::string &path, Directory::ListMode listMode = {true, true}) { + auto dir{OpenDirectoryUnchecked(path, listMode)}; + if (dir == nullptr) + throw exception("Failed to open directory: {}", path); + + return dir; + }; }; } diff --git a/app/src/main/cpp/skyline/vfs/region_backing.h b/app/src/main/cpp/skyline/vfs/region_backing.h index 0765f060..a1d28d00 100644 --- a/app/src/main/cpp/skyline/vfs/region_backing.h +++ b/app/src/main/cpp/skyline/vfs/region_backing.h @@ -16,7 +16,7 @@ namespace skyline::vfs { protected: size_t ReadImpl(span output, size_t offset) override { - return backing->Read(output, baseOffset + offset); + return backing->ReadUnchecked(output, baseOffset + offset); } public: