PKG installer improved

Now it doesn't attempt to delete existing directory and overwrites only
existing files. It should fix installing updates.
This commit is contained in:
Nekotekina 2015-01-04 19:44:54 +03:00
parent 22497757e9
commit 27cfdc897b
3 changed files with 55 additions and 30 deletions

View File

@ -158,24 +158,31 @@ bool LoadEntries(rFile& dec_pkg_f, PKGHeader* m_header, PKGEntry *m_entries)
bool UnpackEntry(rFile& dec_pkg_f, const PKGEntry& entry, std::string dir)
{
u8 buf[BUF_SIZE];
char buf[BUF_SIZE];
dec_pkg_f.Seek(entry.name_offset);
dec_pkg_f.Read(buf, entry.name_size);
buf[entry.name_size] = 0;
switch (entry.type & (0xff))
switch (entry.type.ToBE() >> 24)
{
case PKG_FILE_ENTRY_NPDRM:
case PKG_FILE_ENTRY_NPDRMEDAT:
case PKG_FILE_ENTRY_SDAT:
case PKG_FILE_ENTRY_REGULAR:
case PKG_FILE_ENTRY_NPDRM:
case PKG_FILE_ENTRY_NPDRMEDAT:
case PKG_FILE_ENTRY_SDAT:
case PKG_FILE_ENTRY_REGULAR:
{
rFile out;
auto path = dir + std::string(buf, entry.name_size);
if (rExists(path))
{
LOG_WARNING(LOADER, "PKG Loader: File is overwritten: %s", path.c_str());
}
if (out.Create(path, true /* overwriting */))
{
rFile out;
out.Create(dir + std::string(reinterpret_cast<char *>(buf), entry.name_size));
dec_pkg_f.Seek(entry.file_offset);
for (u64 size = 0; size < entry.file_size; ) {
for (u64 size = 0; size < entry.file_size;) {
size += dec_pkg_f.Read(buf, BUF_SIZE);
if (size > entry.file_size)
out.Write(buf, BUF_SIZE - (size - entry.file_size));
@ -183,14 +190,33 @@ bool UnpackEntry(rFile& dec_pkg_f, const PKGEntry& entry, std::string dir)
out.Write(buf, BUF_SIZE);
}
out.Close();
return true;
}
else
{
LOG_ERROR(LOADER, "PKG Loader: Could not create file: %s", path.c_str());
return false;
}
break;
case PKG_FILE_ENTRY_FOLDER:
rMkdir(dir + std::string(reinterpret_cast<char *>(buf), entry.name_size));
break;
}
return true;
case PKG_FILE_ENTRY_FOLDER:
{
auto path = dir + std::string(buf, entry.name_size);
if (!rExists(path) && !rMkdir(path))
{
LOG_ERROR(LOADER, "PKG Loader: Could not create directory: %s", path.c_str());
return false;
}
return true;
}
default:
{
LOG_ERROR(LOADER, "PKG Loader: unknown PKG file entry: 0x%x", entry.type.ToLE());
return false;
}
}
}
int Unpack(rFile& pkg_f, std::string src, std::string dst)

View File

@ -404,8 +404,7 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
{
const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)Memory.GetBaseAddr();
const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0;
CPUThread* t = GetCurrentCPUThread();
if (u == EXCEPTION_ACCESS_VIOLATION && addr64 < 0x100000000 && t)
if (u == EXCEPTION_ACCESS_VIOLATION && addr64 < 0x100000000)
{
const u32 addr = (u32)addr64;
if (addr >= RAW_SPU_BASE_ADDR && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET) // RawSPU MMIO registers
@ -452,7 +451,7 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
}
default: assert(!"Invalid x64_op_t value");
}
// save x64 reg value (for load operations)
if (save_reg)
{
@ -475,8 +474,15 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
// it's dangerous because destructors won't be executed
}
// TODO: allow recovering from a page fault as a feature of PS3 virtual memory
throw fmt::Format("Access violation %s location 0x%x (is_alive=%d, last_syscall=0x%llx (%s))",
is_writing ? "writing" : "reading", (u32)addr, t->IsAlive() ? 1 : 0, t->m_last_syscall, SysCalls::GetHLEFuncName((u32)t->m_last_syscall).c_str());
if (CPUThread* t = GetCurrentCPUThread())
{
throw fmt::Format("Access violation %s location 0x%x (is_alive=%d, last_syscall=0x%llx (%s))", is_writing ? "writing" : "reading", (u32)addr,
t->IsAlive() ? 1 : 0, t->m_last_syscall, SysCalls::GetHLEFuncName((u32)t->m_last_syscall).c_str());
}
else
{
throw fmt::Format("Access violation %s location 0x%x", is_writing ? "writing" : "reading", (u32)addr);
}
}
// else some fatal error (should crash)
@ -504,8 +510,6 @@ void CPUThread::Task()
#ifdef _WIN32
auto old_se_translator = _set_se_translator(_se_translator);
#else
// TODO: linux version
#endif
try
@ -558,8 +562,6 @@ void CPUThread::Task()
#ifdef _WIN32
_set_se_translator(old_se_translator);
#else
// TODO: linux version
#endif
if (trace.size())

View File

@ -28,16 +28,13 @@ bool PKGLoader::Install(std::string dest)
std::string titleID = std::string(title_id).substr(7, 9);
if (rExists(dest + titleID)) {
rMessageDialog d_overwrite(NULL, "Another installation was found. Do you want to overwrite it?", "PKG Decrypter / Installer", rYES_NO|rCENTRE);
rMessageDialog d_overwrite(NULL, "Another installation found. Do you want to overwrite it?", "PKG Decrypter / Installer", rYES_NO|rCENTRE);
if (d_overwrite.ShowModal() != rID_YES) {
LOG_ERROR(LOADER, "PKG Loader: Another installation found in: %s", titleID.c_str());
return false;
}
rRmdir(dest + titleID);
}
if (!rMkdir(dest + titleID)) {
LOG_ERROR(LOADER, "PKG Loader: Could not make the installation directory: %s", titleID.c_str());
} else if (!rMkdir(dest + titleID)) {
LOG_ERROR(LOADER, "PKG Loader: Could not create the installation directory: %s", titleID.c_str());
return false;
}