mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2024-12-29 11:06:07 +00:00
Fix path bugs & wrap seeks in an if (#1154)
* Fix path bugs * Wrap most seeks in an if
This commit is contained in:
parent
c7ff0419ad
commit
cbbf3505e7
|
@ -372,6 +372,18 @@ bool IOFile::Seek(s64 offset, SeekOrigin origin) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
u64 size = GetSize();
|
||||
if (origin == SeekOrigin::CurrentPosition && Tell() + offset > size) {
|
||||
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
||||
return false;
|
||||
} else if (origin == SeekOrigin::SetOrigin && (u64)offset > size) {
|
||||
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
||||
return false;
|
||||
} else if (origin == SeekOrigin::End && offset > 0) {
|
||||
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
||||
return false;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
||||
const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0;
|
||||
|
|
|
@ -44,7 +44,7 @@ PKG::PKG() = default;
|
|||
|
||||
PKG::~PKG() = default;
|
||||
|
||||
bool PKG::Open(const std::filesystem::path& filepath) {
|
||||
bool PKG::Open(const std::filesystem::path& filepath, std::string& failreason) {
|
||||
Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read);
|
||||
if (!file.IsOpen()) {
|
||||
return false;
|
||||
|
@ -70,7 +70,11 @@ bool PKG::Open(const std::filesystem::path& filepath) {
|
|||
u32 offset = pkgheader.pkg_table_entry_offset;
|
||||
u32 n_files = pkgheader.pkg_table_entry_count;
|
||||
|
||||
file.Seek(offset);
|
||||
if (!file.Seek(offset)) {
|
||||
failreason = "Failed to seek to PKG table entry offset";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < n_files; i++) {
|
||||
PKGEntry entry{};
|
||||
file.Read(entry.id);
|
||||
|
@ -85,7 +89,10 @@ bool PKG::Open(const std::filesystem::path& filepath) {
|
|||
const auto name = GetEntryNameByType(entry.id);
|
||||
if (name == "param.sfo") {
|
||||
sfo.clear();
|
||||
file.Seek(entry.offset);
|
||||
if (!file.Seek(entry.offset)) {
|
||||
failreason = "Failed to seek to param.sfo offset";
|
||||
return false;
|
||||
}
|
||||
sfo.resize(entry.size);
|
||||
file.ReadRaw<u8>(sfo.data(), entry.size);
|
||||
}
|
||||
|
@ -127,7 +134,11 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
|
|||
std::array<std::array<u8, 256>, 7> key1;
|
||||
std::array<u8, 256> imgkeydata;
|
||||
|
||||
file.Seek(offset);
|
||||
if (!file.Seek(offset)) {
|
||||
failreason = "Failed to seek to PKG table entry offset";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < n_files; i++) {
|
||||
PKGEntry entry{};
|
||||
file.Read(entry.id);
|
||||
|
@ -149,7 +160,10 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
|
|||
// Just print with id
|
||||
Common::FS::IOFile out(extract_path / "sce_sys" / std::to_string(entry.id),
|
||||
Common::FS::FileAccessMode::Write);
|
||||
file.Seek(entry.offset);
|
||||
if (!file.Seek(entry.offset)) {
|
||||
failreason = "Failed to seek to PKG entry offset";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<u8> data;
|
||||
data.resize(entry.size);
|
||||
|
@ -195,7 +209,10 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
|
|||
}
|
||||
|
||||
Common::FS::IOFile out(extract_path / "sce_sys" / name, Common::FS::FileAccessMode::Write);
|
||||
file.Seek(entry.offset);
|
||||
if (!file.Seek(entry.offset)) {
|
||||
failreason = "Failed to seek to PKG entry offset";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<u8> data;
|
||||
data.resize(entry.size);
|
||||
|
@ -207,7 +224,10 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
|
|||
if (entry.id == 0x400 || entry.id == 0x401 || entry.id == 0x402 ||
|
||||
entry.id == 0x403) { // somehow 0x401 is not decrypting
|
||||
decNp.resize(entry.size);
|
||||
file.Seek(entry.offset);
|
||||
if (!file.Seek(entry.offset)) {
|
||||
failreason = "Failed to seek to PKG entry offset";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<u8> data;
|
||||
data.resize(entry.size);
|
||||
|
@ -237,7 +257,10 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
|
|||
|
||||
// Read the seed
|
||||
std::array<u8, 16> seed;
|
||||
file.Seek(pkgheader.pfs_image_offset + 0x370);
|
||||
if (!file.Seek(pkgheader.pfs_image_offset + 0x370)) {
|
||||
failreason = "Failed to seek to PFS image offset";
|
||||
return false;
|
||||
}
|
||||
file.Read(seed);
|
||||
|
||||
// Get data and tweak keys.
|
||||
|
|
|
@ -103,7 +103,7 @@ public:
|
|||
PKG();
|
||||
~PKG();
|
||||
|
||||
bool Open(const std::filesystem::path& filepath);
|
||||
bool Open(const std::filesystem::path& filepath, std::string& failreason);
|
||||
void ExtractFiles(const int index);
|
||||
bool Extract(const std::filesystem::path& filepath, const std::filesystem::path& extract,
|
||||
std::string& failreason);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/path_util.h"
|
||||
#include "trp.h"
|
||||
|
||||
|
@ -13,7 +14,10 @@ void TRP::GetNPcommID(const std::filesystem::path& trophyPath, int index) {
|
|||
if (!npbindFile.IsOpen()) {
|
||||
return;
|
||||
}
|
||||
npbindFile.Seek(0x84 + (index * 0x180));
|
||||
if (!npbindFile.Seek(0x84 + (index * 0x180))) {
|
||||
LOG_CRITICAL(Common_Filesystem, "Failed to seek to NPbind offset");
|
||||
return;
|
||||
}
|
||||
npbindFile.ReadRaw<u8>(np_comm_id.data(), 12);
|
||||
std::fill(np_comm_id.begin() + 12, np_comm_id.end(), 0); // fill with 0, we need 16 bytes.
|
||||
}
|
||||
|
@ -56,26 +60,38 @@ bool TRP::Extract(const std::filesystem::path& trophyPath) {
|
|||
std::filesystem::create_directory(trpFilesPath / "Xml");
|
||||
|
||||
for (int i = 0; i < header.entry_num; i++) {
|
||||
file.Seek(seekPos);
|
||||
if (!file.Seek(seekPos)) {
|
||||
LOG_CRITICAL(Common_Filesystem, "Failed to seek to TRP entry offset");
|
||||
return false;
|
||||
}
|
||||
seekPos += (s64)header.entry_size;
|
||||
TrpEntry entry;
|
||||
file.Read(entry);
|
||||
std::string_view name(entry.entry_name);
|
||||
if (entry.flag == 0 && name.find("TROP") != std::string::npos) { // PNG
|
||||
file.Seek(entry.entry_pos);
|
||||
if (file.Seek(entry.entry_pos)) {
|
||||
LOG_CRITICAL(Common_Filesystem, "Failed to seek to TRP entry offset");
|
||||
return false;
|
||||
}
|
||||
std::vector<u8> icon(entry.entry_len);
|
||||
file.Read(icon);
|
||||
Common::FS::IOFile::WriteBytes(trpFilesPath / "Icons" / name, icon);
|
||||
}
|
||||
if (entry.flag == 3 && np_comm_id[0] == 'N' &&
|
||||
np_comm_id[1] == 'P') { // ESFM, encrypted.
|
||||
file.Seek(entry.entry_pos);
|
||||
if (file.Seek(entry.entry_pos)) {
|
||||
LOG_CRITICAL(Common_Filesystem, "Failed to seek to TRP entry offset");
|
||||
return false;
|
||||
}
|
||||
file.Read(esfmIv); // get iv key.
|
||||
// Skip the first 16 bytes which are the iv key on every entry as we want a
|
||||
// clean xml file.
|
||||
std::vector<u8> ESFM(entry.entry_len - iv_len);
|
||||
std::vector<u8> XML(entry.entry_len - iv_len);
|
||||
file.Seek(entry.entry_pos + iv_len);
|
||||
if (file.Seek(entry.entry_pos + iv_len)) {
|
||||
LOG_CRITICAL(Common_Filesystem, "Failed to seek to TRP entry + iv offset");
|
||||
return false;
|
||||
}
|
||||
file.Read(ESFM);
|
||||
crypto.decryptEFSM(np_comm_id, esfmIv, ESFM, XML); // decrypt
|
||||
removePadding(XML);
|
||||
|
|
|
@ -229,7 +229,10 @@ s64 PS4_SYSV_ABI sceKernelLseek(int d, s64 offset, int whence) {
|
|||
}
|
||||
|
||||
std::scoped_lock lk{file->m_mutex};
|
||||
file->f.Seek(offset, origin);
|
||||
if (!file->f.Seek(offset, origin)) {
|
||||
LOG_CRITICAL(Kernel_Fs, "sceKernelLseek: failed to seek");
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
return file->f.Tell();
|
||||
}
|
||||
|
||||
|
@ -380,7 +383,10 @@ s64 PS4_SYSV_ABI sceKernelPread(int d, void* buf, size_t nbytes, s64 offset) {
|
|||
SCOPE_EXIT {
|
||||
file->f.Seek(pos);
|
||||
};
|
||||
file->f.Seek(offset);
|
||||
if (!file->f.Seek(offset)) {
|
||||
LOG_CRITICAL(Kernel_Fs, "sceKernelPread: failed to seek");
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
return file->f.ReadRaw<u8>(buf, nbytes);
|
||||
}
|
||||
|
||||
|
@ -514,7 +520,10 @@ s64 PS4_SYSV_ABI sceKernelPwrite(int d, void* buf, size_t nbytes, s64 offset) {
|
|||
SCOPE_EXIT {
|
||||
file->f.Seek(pos);
|
||||
};
|
||||
file->f.Seek(offset);
|
||||
if (!file->f.Seek(offset)) {
|
||||
LOG_CRITICAL(Kernel_Fs, "sceKernelPwrite: failed to seek");
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
return file->f.WriteRaw<u8>(buf, nbytes);
|
||||
}
|
||||
|
||||
|
|
|
@ -204,7 +204,10 @@ void Elf::Open(const std::filesystem::path& file_name) {
|
|||
}
|
||||
|
||||
out.resize(num);
|
||||
m_f.Seek(offset, SeekOrigin::SetOrigin);
|
||||
if (!m_f.Seek(offset, SeekOrigin::SetOrigin)) {
|
||||
LOG_CRITICAL(Loader, "Failed to seek to header tables");
|
||||
return;
|
||||
}
|
||||
m_f.Read(out);
|
||||
};
|
||||
|
||||
|
@ -465,7 +468,10 @@ std::string Elf::ElfPHeaderStr(u16 no) {
|
|||
void Elf::LoadSegment(u64 virtual_addr, u64 file_offset, u64 size) {
|
||||
if (!is_self) {
|
||||
// It's elf file
|
||||
m_f.Seek(file_offset, SeekOrigin::SetOrigin);
|
||||
if (!m_f.Seek(file_offset, SeekOrigin::SetOrigin)) {
|
||||
LOG_CRITICAL(Loader, "Failed to seek to ELF header");
|
||||
return;
|
||||
}
|
||||
m_f.ReadRaw<u8>(reinterpret_cast<u8*>(virtual_addr), size);
|
||||
return;
|
||||
}
|
||||
|
@ -479,7 +485,10 @@ void Elf::LoadSegment(u64 virtual_addr, u64 file_offset, u64 size) {
|
|||
|
||||
if (file_offset >= phdr.p_offset && file_offset < phdr.p_offset + phdr.p_filesz) {
|
||||
auto offset = file_offset - phdr.p_offset;
|
||||
m_f.Seek(offset + seg.file_offset, SeekOrigin::SetOrigin);
|
||||
if (!m_f.Seek(offset + seg.file_offset, SeekOrigin::SetOrigin)) {
|
||||
LOG_CRITICAL(Loader, "Failed to seek to segment");
|
||||
return;
|
||||
}
|
||||
m_f.ReadRaw<u8>(reinterpret_cast<u8*>(virtual_addr), size);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -312,10 +312,7 @@ public:
|
|||
|
||||
if (selected == &installPackage) {
|
||||
QStringList pkg_app_ = m_pkg_app_list[itemIndex].split(";;");
|
||||
std::filesystem::path path(pkg_app_[9].toStdString());
|
||||
#ifdef _WIN32
|
||||
path = std::filesystem::path(pkg_app_[9].toStdWString());
|
||||
#endif
|
||||
std::filesystem::path path = Common::FS::PathFromQString(pkg_app_[9]);
|
||||
InstallDragDropPkg(path, 1, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -625,10 +625,7 @@ void MainWindow::InstallPkg() {
|
|||
int pkgNum = 0;
|
||||
for (const QString& file : fileNames) {
|
||||
++pkgNum;
|
||||
std::filesystem::path path(file.toStdString());
|
||||
#ifdef _WIN64
|
||||
path = std::filesystem::path(file.toStdWString());
|
||||
#endif
|
||||
std::filesystem::path path = Common::FS::PathFromQString(file);
|
||||
MainWindow::InstallDragDropPkg(path, pkgNum, nPkg);
|
||||
}
|
||||
}
|
||||
|
@ -646,10 +643,7 @@ void MainWindow::BootGame() {
|
|||
QMessageBox::critical(nullptr, tr("Game Boot"),
|
||||
QString(tr("Only one file can be selected!")));
|
||||
} else {
|
||||
std::filesystem::path path(fileNames[0].toStdString());
|
||||
#ifdef _WIN64
|
||||
path = std::filesystem::path(fileNames[0].toStdWString());
|
||||
#endif
|
||||
std::filesystem::path path = Common::FS::PathFromQString(fileNames[0]);
|
||||
Core::Emulator emulator;
|
||||
if (!std::filesystem::exists(path)) {
|
||||
QMessageBox::critical(nullptr, tr("Run Game"),
|
||||
|
@ -663,9 +657,12 @@ void MainWindow::BootGame() {
|
|||
|
||||
void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int nPkg) {
|
||||
if (Loader::DetectFileType(file) == Loader::FileTypes::Pkg) {
|
||||
pkg = PKG();
|
||||
pkg.Open(file);
|
||||
std::string failreason;
|
||||
pkg = PKG();
|
||||
if (!pkg.Open(file, failreason)) {
|
||||
QMessageBox::critical(this, tr("PKG ERROR"), QString::fromStdString(failreason));
|
||||
return;
|
||||
}
|
||||
auto extract_path = Config::getGameInstallDir() / pkg.GetTitleID();
|
||||
QString pkgType = QString::fromStdString(pkg.GetPkgFlags());
|
||||
QString gameDirPath;
|
||||
|
|
|
@ -110,10 +110,7 @@ protected:
|
|||
int nPkg = urlList.size();
|
||||
for (const QUrl& url : urlList) {
|
||||
pkgNum++;
|
||||
std::filesystem::path path(url.toLocalFile().toStdString());
|
||||
#ifdef _WIN64
|
||||
path = std::filesystem::path(url.toLocalFile().toStdWString());
|
||||
#endif
|
||||
std::filesystem::path path = Common::FS::PathFromQString(url.toLocalFile());
|
||||
InstallDragDropPkg(path, pkgNum, nPkg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,11 +104,12 @@ void PKGViewer::ProcessPKGInfo() {
|
|||
m_pkg_patch_list.clear();
|
||||
m_full_pkg_list.clear();
|
||||
for (int i = 0; i < m_pkg_list.size(); i++) {
|
||||
std::filesystem::path path(m_pkg_list[i].toStdString());
|
||||
#ifdef _WIN32
|
||||
path = std::filesystem::path(m_pkg_list[i].toStdWString());
|
||||
#endif
|
||||
package.Open(path);
|
||||
std::filesystem::path path = Common::FS::PathFromQString(m_pkg_list[i]);
|
||||
std::string failreason;
|
||||
if (!package.Open(path, failreason)) {
|
||||
QMessageBox::critical(this, tr("PKG ERROR"), QString::fromStdString(failreason));
|
||||
return;
|
||||
}
|
||||
psf.Open(package.sfo);
|
||||
QString title_name =
|
||||
QString::fromStdString(std::string{psf.GetString("TITLE").value_or("Unknown")});
|
||||
|
|
|
@ -28,10 +28,7 @@ void TrophyViewer::PopulateTrophyWidget(QString title) {
|
|||
|
||||
QDir dir(trophyDirQt);
|
||||
if (!dir.exists()) {
|
||||
std::filesystem::path path(gameTrpPath_.toStdString());
|
||||
#ifdef _WIN64
|
||||
path = std::filesystem::path(gameTrpPath_.toStdWString());
|
||||
#endif
|
||||
std::filesystem::path path = Common::FS::PathFromQString(gameTrpPath_);
|
||||
if (!trp.Extract(path))
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue