mirror of
https://github.com/mmozeiko/pkg2zip.git
synced 2026-09-02 19:23:09 +03:00
fixing unicode output on Windows
This commit is contained in:
@@ -25,10 +25,9 @@ static const uint8_t pkg_vita_4[] = { 0xaf, 0x07, 0xfd, 0x59, 0x65, 0x25, 0x27,
|
||||
// https://github.com/TheOfficialFloW/VitaShell/blob/1.74/sfo.h#L29
|
||||
static void parse_sfo_content(const uint8_t* sfo, uint32_t sfo_size, char* category, char* title, char* content, char* min_version, char* pkg_version)
|
||||
{
|
||||
|
||||
if (get32le(sfo) != 0x46535000)
|
||||
{
|
||||
fatal("ERROR: incorrect sfo signature\n");
|
||||
sys_error("ERROR: incorrect sfo signature\n");
|
||||
}
|
||||
|
||||
uint32_t keys = get32le(sfo + 8);
|
||||
@@ -44,7 +43,7 @@ static void parse_sfo_content(const uint8_t* sfo, uint32_t sfo_size, char* categ
|
||||
{
|
||||
if (i * 16 + 20 + 2 > sfo_size)
|
||||
{
|
||||
fatal("ERROR: sfo information is too small\n");
|
||||
sys_error("ERROR: sfo information is too small\n");
|
||||
}
|
||||
|
||||
char* key = (char*)sfo + keys + get16le(sfo + i * 16 + 20);
|
||||
@@ -79,7 +78,7 @@ static void parse_sfo_content(const uint8_t* sfo, uint32_t sfo_size, char* categ
|
||||
|
||||
if (title_index < 0)
|
||||
{
|
||||
fatal("ERROR: cannot find title from sfo file, pkg is probably corrupted\n");
|
||||
sys_error("ERROR: cannot find title from sfo file, pkg is probably corrupted\n");
|
||||
}
|
||||
|
||||
char* value = (char*)sfo + values + get32le(sfo + title_index * 16 + 20 + 12);
|
||||
@@ -168,11 +167,11 @@ static void parse_sfo(sys_file f, uint64_t sfo_offset, uint32_t sfo_size, char*
|
||||
uint8_t sfo[16 * 1024];
|
||||
if (sfo_size < 16)
|
||||
{
|
||||
fatal("ERROR: sfo information is too small\n");
|
||||
sys_error("ERROR: sfo information is too small\n");
|
||||
}
|
||||
if (sfo_size > sizeof(sfo))
|
||||
{
|
||||
fatal("ERROR: sfo information is too big, pkg file is probably corrupted\n");
|
||||
sys_error("ERROR: sfo information is too big, pkg file is probably corrupted\n");
|
||||
}
|
||||
sys_read(f, sfo_offset, sfo, sfo_size);
|
||||
|
||||
@@ -200,7 +199,7 @@ static void find_psp_sfo(const aes128_key* key, const aes128_key* ps3_key, const
|
||||
if (pkg_size < enc_offset + name_offset + name_size ||
|
||||
pkg_size < enc_offset + data_offset + data_size)
|
||||
{
|
||||
fatal("ERROR: pkg file is too short, possibly corrupted\n");
|
||||
sys_error("ERROR: pkg file is too short, possibly corrupted\n");
|
||||
}
|
||||
|
||||
const aes128_key* item_key = psp_type == 0x90 ? key : ps3_key;
|
||||
@@ -215,11 +214,11 @@ static void find_psp_sfo(const aes128_key* key, const aes128_key* ps3_key, const
|
||||
uint8_t sfo[16 * 1024];
|
||||
if (data_size < 16)
|
||||
{
|
||||
fatal("ERROR: sfo information is too small\n");
|
||||
sys_error("ERROR: sfo information is too small\n");
|
||||
}
|
||||
if (data_size > sizeof(sfo))
|
||||
{
|
||||
fatal("ERROR: sfo information is too big, pkg file is probably corrupted\n");
|
||||
sys_error("ERROR: sfo information is too big, pkg file is probably corrupted\n");
|
||||
}
|
||||
|
||||
sys_read(pkg, enc_offset + data_offset, sfo, (uint32_t)data_size);
|
||||
@@ -272,7 +271,8 @@ typedef enum {
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
printf("pkg2zip v1.8\n");
|
||||
sys_output_init();
|
||||
sys_output("pkg2zip v1.8\n");
|
||||
|
||||
int zipped = 1;
|
||||
int cso = 5;
|
||||
@@ -309,10 +309,10 @@ int main(int argc, char* argv[])
|
||||
if (pkg_arg == NULL)
|
||||
{
|
||||
fprintf(stderr, "ERROR: no pkg file specified\n");
|
||||
fatal("Usage: %s [-x] [-c[N]] file.pkg [zRIF]\n", argv[0]);
|
||||
sys_error("Usage: %s [-x] [-c[N]] file.pkg [zRIF]\n", argv[0]);
|
||||
}
|
||||
|
||||
printf("[*] loading...\n");
|
||||
sys_output("[*] loading...\n");
|
||||
|
||||
uint64_t pkg_size;
|
||||
sys_file pkg = sys_open(pkg_arg, &pkg_size);
|
||||
@@ -322,7 +322,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (get32be(pkg_header) != 0x7f504b47 || get32be(pkg_header + PKG_HEADER_SIZE) != 0x7F657874)
|
||||
{
|
||||
fatal("ERROR: not a pkg file\n");
|
||||
sys_error("ERROR: not a pkg file\n");
|
||||
}
|
||||
|
||||
// http://www.psdevwiki.com/ps3/PKG_files
|
||||
@@ -337,11 +337,11 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (pkg_size < total_size)
|
||||
{
|
||||
fatal("ERROR: pkg file is too small\n");
|
||||
sys_error("ERROR: pkg file is too small\n");
|
||||
}
|
||||
if (pkg_size < enc_offset + item_count * 32)
|
||||
{
|
||||
fatal("ERROR: pkg file is too small\n");
|
||||
sys_error("ERROR: pkg file is too small\n");
|
||||
}
|
||||
|
||||
uint32_t content_type = 0;
|
||||
@@ -402,7 +402,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
else
|
||||
{
|
||||
fatal("ERROR: unsupported content type 0x%x", content_type);
|
||||
sys_error("ERROR: unsupported content type 0x%x", content_type);
|
||||
}
|
||||
|
||||
aes128_key ps3_key;
|
||||
@@ -476,7 +476,7 @@ int main(int argc, char* argv[])
|
||||
const char* rif_contentid = (char*)rif + (type == PKG_TYPE_VITA_PSM ? 0x50 : 0x10);
|
||||
if (strncmp(rif_contentid, content, 0x30) != 0)
|
||||
{
|
||||
fatal("ERROR: zRIF content id '%s' doesn't match pkg '%s'\n", rif_contentid, content);
|
||||
sys_error("ERROR: zRIF content id '%s' doesn't match pkg '%s'\n", rif_contentid, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -496,42 +496,42 @@ int main(int argc, char* argv[])
|
||||
type_str = content_type == 0xe ? "PSP-Go" : content_type == 0xf ? "PSP-Mini" : "PSP-NeoGeo";
|
||||
}
|
||||
snprintf(root, sizeof(root), "%s [%.9s] [%s]%s", title, id, type_str, ext);
|
||||
printf("[*] unpacking %s\n", type_str);
|
||||
sys_output("[*] unpacking %s\n", type_str);
|
||||
}
|
||||
else if (type == PKG_TYPE_PSX)
|
||||
{
|
||||
snprintf(root, sizeof(root), "%s [%.9s] [PSX]%s", title, id, ext);
|
||||
printf("[*] unpacking PSX\n");
|
||||
sys_output("[*] unpacking PSX\n");
|
||||
}
|
||||
else if (type == PKG_TYPE_VITA_DLC)
|
||||
{
|
||||
snprintf(root, sizeof(root), "%s [%.9s] [%s] [DLC-%s]%s", title, id, get_region(id), id2, ext);
|
||||
printf("[*] unpacking DLC\n");
|
||||
sys_output("[*] unpacking DLC\n");
|
||||
}
|
||||
else if (type == PKG_TYPE_VITA_PATCH)
|
||||
{
|
||||
snprintf(root, sizeof(root), "%s [%.9s] [%s] [PATCH] [v%s]%s", title, id, get_region(id), pkg_version, ext);
|
||||
printf("[*] unpacking PATCH\n");
|
||||
sys_output("[*] unpacking PATCH\n");
|
||||
}
|
||||
else if (type == PKG_TYPE_VITA_PSM)
|
||||
{
|
||||
snprintf(root, sizeof(root), "%.9s [%s]%s", id, get_region(id), ext);
|
||||
printf("[*] unpacking PSM\n");
|
||||
sys_output("[*] unpacking PSM\n");
|
||||
}
|
||||
else if (type == PKG_TYPE_VITA_APP)
|
||||
{
|
||||
snprintf(root, sizeof(root), "%s [%.9s] [%s]%s", title, id, get_region(id), ext);
|
||||
printf("[*] unpacking APP\n");
|
||||
sys_output("[*] unpacking APP\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
fatal("ERROR: unsupported type\n");
|
||||
sys_error("ERROR: unsupported type\n");
|
||||
}
|
||||
|
||||
if (zipped)
|
||||
{
|
||||
printf("[*] creating '%s' archive\n", root);
|
||||
sys_output("[*] creating '%s' archive\n", root);
|
||||
}
|
||||
|
||||
out_begin(root, zipped);
|
||||
@@ -603,10 +603,10 @@ int main(int argc, char* argv[])
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
fatal("ERROR: unsupported type\n");
|
||||
sys_error("ERROR: unsupported type\n");
|
||||
}
|
||||
|
||||
printf("[*] decrypting...\n");
|
||||
sys_output("[*] decrypting...\n");
|
||||
char path[1024];
|
||||
|
||||
int sce_sys_package_created = 0;
|
||||
@@ -631,12 +631,12 @@ int main(int argc, char* argv[])
|
||||
if (pkg_size < enc_offset + name_offset + name_size ||
|
||||
pkg_size < enc_offset + data_offset + data_size)
|
||||
{
|
||||
fatal("ERROR: pkg file is too short, possibly corrupted\n");
|
||||
sys_error("ERROR: pkg file is too short, possibly corrupted\n");
|
||||
}
|
||||
|
||||
if (name_size >= ZIP_MAX_FILENAME)
|
||||
{
|
||||
fatal("ERROR: pkg file contains file with very long name\n");
|
||||
sys_error("ERROR: pkg file contains file with very long name\n");
|
||||
}
|
||||
|
||||
const aes128_key* item_key;
|
||||
@@ -654,7 +654,7 @@ int main(int argc, char* argv[])
|
||||
aes128_ctr_xor(item_key, iv, name_offset / 16, (uint8_t*)name, name_size);
|
||||
name[name_size] = 0;
|
||||
|
||||
printf("[%u/%u] %s\n", item_index + 1, item_count, name);
|
||||
sys_output("[%u/%u] %s\n", item_index + 1, item_count, name);
|
||||
|
||||
if (flags == 4 || flags == 18)
|
||||
{
|
||||
@@ -770,12 +770,12 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
if (!sce_sys_package_created)
|
||||
{
|
||||
printf("[*] creating sce_sys/package\n");
|
||||
sys_output("[*] creating sce_sys/package\n");
|
||||
snprintf(path, sizeof(path), "%s/sce_sys/package", root);
|
||||
out_add_folder(path);
|
||||
}
|
||||
|
||||
printf("[*] creating sce_sys/package/head.bin\n");
|
||||
sys_output("[*] creating sce_sys/package/head.bin\n");
|
||||
snprintf(path, sizeof(path), "%s/sce_sys/package/head.bin", root);
|
||||
|
||||
out_begin_file(path, 0);
|
||||
@@ -792,7 +792,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
out_end_file();
|
||||
|
||||
printf("[*] creating sce_sys/package/tail.bin\n");
|
||||
sys_output("[*] creating sce_sys/package/tail.bin\n");
|
||||
snprintf(path, sizeof(path), "%s/sce_sys/package/tail.bin", root);
|
||||
|
||||
out_begin_file(path, 0);
|
||||
@@ -807,7 +807,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
out_end_file();
|
||||
|
||||
printf("[*] creating sce_sys/package/stat.bin\n");
|
||||
sys_output("[*] creating sce_sys/package/stat.bin\n");
|
||||
snprintf(path, sizeof(path), "%s/sce_sys/package/stat.bin", root);
|
||||
|
||||
uint8_t stat[768] = { 0 };
|
||||
@@ -820,16 +820,16 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
if (type == PKG_TYPE_VITA_PSM)
|
||||
{
|
||||
printf("[*] creating RO/License\n");
|
||||
sys_output("[*] creating RO/License\n");
|
||||
snprintf(path, sizeof(path), "%s/RO/License", root);
|
||||
out_add_folder(path);
|
||||
|
||||
printf("[*] creating RO/License/FAKE.rif\n");
|
||||
sys_output("[*] creating RO/License/FAKE.rif\n");
|
||||
snprintf(path, sizeof(path), "%s/RO/License/FAKE.rif", root);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[*] creating sce_sys/package/work.bin\n");
|
||||
sys_output("[*] creating sce_sys/package/work.bin\n");
|
||||
snprintf(path, sizeof(path), "%s/sce_sys/package/work.bin", root);
|
||||
}
|
||||
|
||||
@@ -840,29 +840,29 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (type == PKG_TYPE_VITA_PSM)
|
||||
{
|
||||
printf("[*] creating RW\n");
|
||||
sys_output("[*] creating RW\n");
|
||||
snprintf(path, sizeof(path), "%s/RW", root);
|
||||
out_add_folder(path);
|
||||
|
||||
printf("[*] creating RW/Documents\n");
|
||||
sys_output("[*] creating RW/Documents\n");
|
||||
snprintf(path, sizeof(path), "%s/RW/Documents", root);
|
||||
out_add_folder(path);
|
||||
|
||||
printf("[*] creating RW/Temp\n");
|
||||
sys_output("[*] creating RW/Temp\n");
|
||||
snprintf(path, sizeof(path), "%s/RW/Temp", root);
|
||||
out_add_folder(path);
|
||||
|
||||
printf("[*] creating RW/System\n");
|
||||
sys_output("[*] creating RW/System\n");
|
||||
snprintf(path, sizeof(path), "%s/RW/System", root);
|
||||
out_add_folder(path);
|
||||
|
||||
printf("[*] creating RW/System/content_id\n");
|
||||
sys_output("[*] creating RW/System/content_id\n");
|
||||
snprintf(path, sizeof(path), "%s/RW/System/content_id", root);
|
||||
out_begin_file(path, 0);
|
||||
out_write(pkg_header + 0x30, 0x30);
|
||||
out_end_file();
|
||||
|
||||
printf("[*] creating RW/System/pm.dat\n");
|
||||
sys_output("[*] creating RW/System/pm.dat\n");
|
||||
snprintf(path, sizeof(path), "%s/RW/System/pm.dat", root);
|
||||
|
||||
uint8_t pm[1 << 16] = { 0 };
|
||||
@@ -875,8 +875,8 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (type == PKG_TYPE_VITA_APP || type == PKG_TYPE_VITA_PATCH)
|
||||
{
|
||||
printf("[*] minimum fw version required: %s\n", min_version);
|
||||
sys_output("[*] minimum fw version required: %s\n", min_version);
|
||||
}
|
||||
|
||||
printf("[*] done!\n");
|
||||
sys_output("[*] done!\n");
|
||||
}
|
||||
|
||||
+16
-16
@@ -50,7 +50,7 @@ static void rc_init(lzrc_decode* rc, void* out, int out_len, const void* in, int
|
||||
{
|
||||
if (in_len < 5)
|
||||
{
|
||||
fatal("ERROR: internal error - lzrc input underflow! pkg may be corrupted?\n");
|
||||
sys_error("ERROR: internal error - lzrc input underflow! pkg may be corrupted?\n");
|
||||
}
|
||||
|
||||
rc->input = in;
|
||||
@@ -199,7 +199,7 @@ static int lzrc_decompress(void* out, int out_len, const void* in, int in_len)
|
||||
|
||||
if (rc.out_ptr == rc.out_len)
|
||||
{
|
||||
fatal("ERROR: internal error - lzrc output overflow! pkg may be corrupted?\n");
|
||||
sys_error("ERROR: internal error - lzrc output overflow! pkg may be corrupted?\n");
|
||||
}
|
||||
rc.output[rc.out_ptr++] = (uint8_t)byte;
|
||||
last_byte = (uint8_t)byte;
|
||||
@@ -261,12 +261,12 @@ static int lzrc_decompress(void* out, int out_len, const void* in, int in_len)
|
||||
// copy match bytes
|
||||
if (match_dist > rc.out_ptr)
|
||||
{
|
||||
fatal("ERROR: internal error - lzrc match_dist out of range! pkg may be corrupted?\n");
|
||||
sys_error("ERROR: internal error - lzrc match_dist out of range! pkg may be corrupted?\n");
|
||||
}
|
||||
|
||||
if (rc.out_ptr + match_len + 1 > rc.out_len)
|
||||
{
|
||||
fatal("ERROR: internal error - lzrc output overflow! pkg may be corrupted?\n");
|
||||
sys_error("ERROR: internal error - lzrc output overflow! pkg may be corrupted?\n");
|
||||
}
|
||||
|
||||
const uint8_t* match_src = rc.output + rc.out_ptr - match_dist;
|
||||
@@ -315,7 +315,7 @@ void unpack_psp_eboot(const char* path, const aes128_key* pkg_key, const uint8_t
|
||||
{
|
||||
if (item_size < 0x28)
|
||||
{
|
||||
fatal("ERROR: eboot.pbp file is to short!\n");
|
||||
sys_error("ERROR: eboot.pbp file is to short!\n");
|
||||
}
|
||||
|
||||
uint8_t eboot_header[0x28];
|
||||
@@ -324,13 +324,13 @@ void unpack_psp_eboot(const char* path, const aes128_key* pkg_key, const uint8_t
|
||||
|
||||
if (memcmp(eboot_header, "\x00PBP", 4) != 0)
|
||||
{
|
||||
fatal("ERROR: wrong eboot.pbp header signature!\n");
|
||||
sys_error("ERROR: wrong eboot.pbp header signature!\n");
|
||||
}
|
||||
|
||||
uint32_t psar_offset = get32le(eboot_header + 0x24);
|
||||
if (psar_offset + 256 > item_size)
|
||||
{
|
||||
fatal("ERROR: eboot.pbp file is to short!\n");
|
||||
sys_error("ERROR: eboot.pbp file is to short!\n");
|
||||
}
|
||||
assert(psar_offset % 16 == 0);
|
||||
|
||||
@@ -340,13 +340,13 @@ void unpack_psp_eboot(const char* path, const aes128_key* pkg_key, const uint8_t
|
||||
|
||||
if (memcmp(psar_header, "NPUMDIMG", 8) != 0)
|
||||
{
|
||||
fatal("ERROR: wrong data.psar header signature!\n");
|
||||
sys_error("ERROR: wrong data.psar header signature!\n");
|
||||
}
|
||||
|
||||
uint32_t iso_block = get32le(psar_header + 0x0c);
|
||||
if (iso_block > 16)
|
||||
{
|
||||
fatal("ERROR: unsupported data.psar block size %u, max %u supported!\b", iso_block, 16);
|
||||
sys_error("ERROR: unsupported data.psar block size %u, max %u supported!\b", iso_block, 16);
|
||||
}
|
||||
|
||||
uint8_t mac[16];
|
||||
@@ -366,7 +366,7 @@ void unpack_psp_eboot(const char* path, const aes128_key* pkg_key, const uint8_t
|
||||
|
||||
if (iso_table + block_count * 32 > item_size)
|
||||
{
|
||||
fatal("ERROR: offset table in data.psar file is too large!\n");
|
||||
sys_error("ERROR: offset table in data.psar file is too large!\n");
|
||||
}
|
||||
|
||||
mz_uint cso_compress_flags = 0;
|
||||
@@ -411,7 +411,7 @@ void unpack_psp_eboot(const char* path, const aes128_key* pkg_key, const uint8_t
|
||||
|
||||
if (psar_offset + block_size > item_size)
|
||||
{
|
||||
fatal("ERROR: iso block size/offset is to large!\n");
|
||||
sys_error("ERROR: iso block size/offset is to large!\n");
|
||||
}
|
||||
|
||||
uint8_t PKG_ALIGN(16) data[16 * ISO_SECTOR_SIZE];
|
||||
@@ -466,7 +466,7 @@ void unpack_psp_eboot(const char* path, const aes128_key* pkg_key, const uint8_t
|
||||
out_size = lzrc_decompress(uncompressed, sizeof(uncompressed), data, block_size);
|
||||
if (out_size != iso_block * ISO_SECTOR_SIZE)
|
||||
{
|
||||
fatal("ERROR: internal error - lzrc decompression failed! pkg may be corrupted?\n");
|
||||
sys_error("ERROR: internal error - lzrc decompression failed! pkg may be corrupted?\n");
|
||||
}
|
||||
if (cso)
|
||||
{
|
||||
@@ -541,7 +541,7 @@ void unpack_psp_key(const char* path, const aes128_key* pkg_key, const uint8_t*
|
||||
{
|
||||
if (item_size < 0x90 + 0xa0)
|
||||
{
|
||||
fatal("ERROR: PSP-KEY.EDAT file is to short!\n");
|
||||
sys_error("ERROR: PSP-KEY.EDAT file is to short!\n");
|
||||
}
|
||||
|
||||
uint8_t key_header[0xa0];
|
||||
@@ -550,14 +550,14 @@ void unpack_psp_key(const char* path, const aes128_key* pkg_key, const uint8_t*
|
||||
|
||||
if (memcmp(key_header, "\x00PGD", 4) != 0)
|
||||
{
|
||||
fatal("ERROR: wrong PSP-KEY.EDAT header signature!\n");
|
||||
sys_error("ERROR: wrong PSP-KEY.EDAT header signature!\n");
|
||||
}
|
||||
|
||||
uint32_t key_index = get32le(key_header + 4);
|
||||
uint32_t drm_type = get32le(key_header + 8);
|
||||
if (key_index != 1 || drm_type != 1)
|
||||
{
|
||||
fatal("ERROR: unsupported PSP-KEY.EDAT file, key/drm type is wrong!\n");
|
||||
sys_error("ERROR: unsupported PSP-KEY.EDAT file, key/drm type is wrong!\n");
|
||||
}
|
||||
|
||||
uint8_t mac[16];
|
||||
@@ -573,7 +573,7 @@ void unpack_psp_key(const char* path, const aes128_key* pkg_key, const uint8_t*
|
||||
|
||||
if (data_size != 0x10 || data_offset != 0x90)
|
||||
{
|
||||
fatal("ERROR: unsupported PSP-KEY.EDAT file, data/offset is wrong!\n");
|
||||
sys_error("ERROR: unsupported PSP-KEY.EDAT file, data/offset is wrong!\n");
|
||||
}
|
||||
|
||||
init_psp_decrypt(&psp_key, psp_iv, 0, mac, key_header, 0x70, 0x30);
|
||||
|
||||
+96
-16
@@ -11,6 +11,64 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
static HANDLE gStdout;
|
||||
static int gStdoutRedirected;
|
||||
|
||||
void sys_output_init(void)
|
||||
{
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
gStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
DWORD mode;
|
||||
gStdoutRedirected = !GetConsoleMode(gStdout, &mode);
|
||||
}
|
||||
|
||||
void sys_output(const char* msg, ...)
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
va_list arg;
|
||||
va_start(arg, msg);
|
||||
vsnprintf(buffer, sizeof(buffer), msg, arg);
|
||||
va_end(arg);
|
||||
|
||||
if (!gStdoutRedirected)
|
||||
{
|
||||
WCHAR wbuffer[sizeof(buffer)];
|
||||
int wcount = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, wbuffer, sizeof(buffer));
|
||||
|
||||
DWORD written;
|
||||
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wbuffer, wcount, &written, NULL);
|
||||
return;
|
||||
}
|
||||
fputs(buffer, stdout);
|
||||
}
|
||||
|
||||
void sys_error(const char* msg, ...)
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
va_list arg;
|
||||
va_start(arg, msg);
|
||||
vsnprintf(buffer, sizeof(buffer), msg, arg);
|
||||
va_end(arg);
|
||||
|
||||
DWORD mode;
|
||||
if (GetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), &mode))
|
||||
{
|
||||
WCHAR wbuffer[sizeof(buffer)];
|
||||
int wcount = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, wbuffer, sizeof(buffer));
|
||||
|
||||
DWORD written;
|
||||
WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wbuffer, wcount, &written, NULL);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fputs(buffer, stderr);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void sys_mkdir_real(const char* path)
|
||||
{
|
||||
WCHAR wpath[MAX_PATH];
|
||||
@@ -20,7 +78,7 @@ static void sys_mkdir_real(const char* path)
|
||||
{
|
||||
if (GetLastError() != ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
fatal("ERROR: cannot create '%s' folder\n", path);
|
||||
sys_error("ERROR: cannot create '%s' folder\n", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,13 +91,13 @@ sys_file sys_open(const char* fname, uint64_t* size)
|
||||
HANDLE handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
fatal("ERROR: cannot open '%s' file\n", fname);
|
||||
sys_error("ERROR: cannot open '%s' file\n", fname);
|
||||
}
|
||||
|
||||
LARGE_INTEGER sz;
|
||||
if (!GetFileSizeEx(handle, &sz))
|
||||
{
|
||||
fatal("ERROR: cannot get size of '%s' file\n", fname);
|
||||
sys_error("ERROR: cannot get size of '%s' file\n", fname);
|
||||
}
|
||||
*size = sz.QuadPart;
|
||||
|
||||
@@ -54,7 +112,7 @@ sys_file sys_create(const char* fname)
|
||||
HANDLE handle = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
fatal("ERROR: cannot create '%s' file\n", fname);
|
||||
sys_error("ERROR: cannot create '%s' file\n", fname);
|
||||
}
|
||||
|
||||
return handle;
|
||||
@@ -64,7 +122,7 @@ void sys_close(sys_file file)
|
||||
{
|
||||
if (!CloseHandle(file))
|
||||
{
|
||||
fatal("ERROR: failed to close file\n");
|
||||
sys_error("ERROR: failed to close file\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +135,7 @@ void sys_read(sys_file file, uint64_t offset, void* buffer, uint32_t size)
|
||||
ov.OffsetHigh = (uint32_t)(offset >> 32);
|
||||
if (!ReadFile(file, buffer, size, &read, &ov) || read != size)
|
||||
{
|
||||
fatal("ERROR: failed to read %u bytes from file\n", size);
|
||||
sys_error("ERROR: failed to read %u bytes from file\n", size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +148,7 @@ void sys_write(sys_file file, uint64_t offset, const void* buffer, uint32_t size
|
||||
ov.OffsetHigh = (uint32_t)(offset >> 32);
|
||||
if (!WriteFile(file, buffer, size, &written, &ov) || written != size)
|
||||
{
|
||||
fatal("ERROR: failed to write %u bytes to file\n", size);
|
||||
sys_error("ERROR: failed to write %u bytes to file\n", size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,13 +161,35 @@ void sys_write(sys_file file, uint64_t offset, const void* buffer, uint32_t size
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
void sys_output_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void sys_output(const char* msg, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, msg);
|
||||
vfprintf(stdout, msg, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
void sys_error(const char* msg, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, msg);
|
||||
vfprintf(stderr, msg, arg);
|
||||
va_end(arg);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void sys_mkdir_real(const char* path)
|
||||
{
|
||||
if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
|
||||
{
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
fatal("ERROR: cannot create '%s' folder\n", path);
|
||||
sys_error("ERROR: cannot create '%s' folder\n", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,13 +199,13 @@ sys_file sys_open(const char* fname, uint64_t* size)
|
||||
int fd = open(fname, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
fatal("ERROR: cannot open '%s' file\n", fname);
|
||||
error("ERROR: cannot open '%s' file\n", fname);
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) != 0)
|
||||
{
|
||||
fatal("ERROR: cannot get size of '%s' file\n", fname);
|
||||
sys_error("ERROR: cannot get size of '%s' file\n", fname);
|
||||
}
|
||||
*size = st.st_size;
|
||||
|
||||
@@ -137,7 +217,7 @@ sys_file sys_create(const char* fname)
|
||||
int fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (fd < 0)
|
||||
{
|
||||
fatal("ERROR: cannot create '%s' file\n", fname);
|
||||
sys_error("ERROR: cannot create '%s' file\n", fname);
|
||||
}
|
||||
|
||||
return (void*)(intptr_t)fd;
|
||||
@@ -147,7 +227,7 @@ void sys_close(sys_file file)
|
||||
{
|
||||
if (close((int)(intptr_t)file) != 0)
|
||||
{
|
||||
fatal("ERROR: failed to close file\n");
|
||||
sys_error("ERROR: failed to close file\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +236,7 @@ void sys_read(sys_file file, uint64_t offset, void* buffer, uint32_t size)
|
||||
ssize_t read = pread((int)(intptr_t)file, buffer, size, offset);
|
||||
if (read < 0 || read != (ssize_t)size)
|
||||
{
|
||||
fatal("ERROR: failed to read %u bytes from file\n", size);
|
||||
sys_error("ERROR: failed to read %u bytes from file\n", size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +245,7 @@ void sys_write(sys_file file, uint64_t offset, const void* buffer, uint32_t size
|
||||
ssize_t wrote = pwrite((int)(intptr_t)file, buffer, size, offset);
|
||||
if (wrote < 0 || wrote != (ssize_t)size)
|
||||
{
|
||||
fatal("ERROR: failed to read %u bytes from file\n", size);
|
||||
sys_error("ERROR: failed to read %u bytes from file\n", size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,12 +281,12 @@ void* sys_realloc(void* ptr, size_t size)
|
||||
}
|
||||
else
|
||||
{
|
||||
fatal("ERROR: internal error, wrong sys_realloc usage\n");
|
||||
sys_error("ERROR: internal error, wrong sys_realloc usage\n");
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
fatal("ERROR: out of memory\n");
|
||||
sys_error("ERROR: out of memory\n");
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
+6
-2
@@ -1,7 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "pkg2zip_utils.h"
|
||||
|
||||
// correctly outputs utf8 string
|
||||
void sys_output_init(void);
|
||||
void sys_output(const char* msg, ...);
|
||||
void NORETURN sys_error(const char* msg, ...);
|
||||
|
||||
typedef void* sys_file;
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#include "pkg2zip_utils.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void fatal(const char* msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
vfprintf(stderr, msg, args);
|
||||
va_end(args);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -11,8 +11,6 @@
|
||||
# define PKG_ALIGN(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
|
||||
void NORETURN fatal(const char* msg, ...);
|
||||
|
||||
static inline uint32_t min32(uint32_t a, uint32_t b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
|
||||
+4
-3
@@ -4,6 +4,7 @@
|
||||
#endif
|
||||
|
||||
#include "pkg2zip_zip.h"
|
||||
#include "pkg2zip_out.h"
|
||||
#include "pkg2zip_crc32.h"
|
||||
#include "pkg2zip_utils.h"
|
||||
|
||||
@@ -73,7 +74,7 @@ void zip_add_folder(zip* z, const char* name)
|
||||
size_t name_length = strlen(name) + 1;
|
||||
if (name_length > ZIP_MAX_FILENAME)
|
||||
{
|
||||
fatal("ERROR: dirname too long\n");
|
||||
sys_error("ERROR: dirname too long\n");
|
||||
}
|
||||
|
||||
zip_file* f = zip_new_file(z);
|
||||
@@ -113,7 +114,7 @@ uint64_t zip_begin_file(zip* z, const char* name, int compress)
|
||||
size_t name_length = strlen(name);
|
||||
if (name_length > ZIP_MAX_FILENAME)
|
||||
{
|
||||
fatal("ERROR: filename too long\n");
|
||||
sys_error("ERROR: filename too long\n");
|
||||
}
|
||||
|
||||
zip_file* f = zip_new_file(z);
|
||||
@@ -411,7 +412,7 @@ void zip_write_file_at(zip* z, uint64_t offset, const void* data, uint32_t size)
|
||||
{
|
||||
if (z->current->compress)
|
||||
{
|
||||
fatal("ERROR: cannot write at specific offset for compressed files\n");
|
||||
sys_error("ERROR: cannot write at specific offset for compressed files\n");
|
||||
}
|
||||
|
||||
sys_write(z->file, z->current->offset + offset, data, size);
|
||||
|
||||
+8
-7
@@ -1,5 +1,6 @@
|
||||
#include "pkg2zip_zrif.h"
|
||||
#include "pkg2zip_utils.h"
|
||||
#include "pkg2zip_sys.h"
|
||||
#include "miniz_tdef.h"
|
||||
#include "puff.h"
|
||||
|
||||
@@ -106,17 +107,17 @@ static uint32_t zlib_inflate(const uint8_t* in, uint32_t inlen, uint8_t* out, ui
|
||||
{
|
||||
if (inlen < 2 + 4)
|
||||
{
|
||||
fatal("ERROR: zRIF length too short\n");
|
||||
sys_error("ERROR: zRIF length too short\n");
|
||||
}
|
||||
|
||||
if (((in[0] << 8) + in[1]) % 31 != 0)
|
||||
{
|
||||
fatal("ERROR: zRIF header is corrupted\n");
|
||||
sys_error("ERROR: zRIF header is corrupted\n");
|
||||
}
|
||||
|
||||
if ((in[0] & 0xf) != ZLIB_DEFLATE_METHOD)
|
||||
{
|
||||
fatal("ERROR: only deflate method supported in zRIF\n");
|
||||
sys_error("ERROR: only deflate method supported in zRIF\n");
|
||||
}
|
||||
|
||||
unsigned long slen = inlen - 4;
|
||||
@@ -132,7 +133,7 @@ static uint32_t zlib_inflate(const uint8_t* in, uint32_t inlen, uint8_t* out, ui
|
||||
|
||||
if (get32be(in + 2) != ZLIB_DICTIONARY_ID_ZRIF)
|
||||
{
|
||||
fatal("ERROR: zRIF uses unknown dictionary\n");
|
||||
sys_error("ERROR: zRIF uses unknown dictionary\n");
|
||||
}
|
||||
|
||||
in += 6;
|
||||
@@ -146,13 +147,13 @@ static uint32_t zlib_inflate(const uint8_t* in, uint32_t inlen, uint8_t* out, ui
|
||||
|
||||
if (puff(dictlen, out, &dlen, in, &slen) != 0)
|
||||
{
|
||||
fatal("ERROR: failed to uncompress zRIF\n");
|
||||
sys_error("ERROR: failed to uncompress zRIF\n");
|
||||
}
|
||||
memmove(out, out + dictlen, dlen);
|
||||
|
||||
if (mz_adler32(MZ_ADLER32_INIT, out, dlen) != get32be(in + slen))
|
||||
{
|
||||
fatal("ERROR: zRIF is corrupted, wrong checksum\n");
|
||||
sys_error("ERROR: zRIF is corrupted, wrong checksum\n");
|
||||
}
|
||||
|
||||
return dlen;
|
||||
@@ -167,7 +168,7 @@ void zrif_decode(const char* str, uint8_t* rif, uint32_t rif_size)
|
||||
len = zlib_inflate(raw, len, out, sizeof(out));
|
||||
if (len != rif_size)
|
||||
{
|
||||
fatal("ERROR: wrong size of zRIF, is it corrupted?\n");
|
||||
sys_error("ERROR: wrong size of zRIF, is it corrupted?\n");
|
||||
}
|
||||
|
||||
memcpy(rif, out, rif_size);
|
||||
|
||||
Reference in New Issue
Block a user