diff --git a/pkg2zip.c b/pkg2zip.c index 7b19640..c0037e1 100644 --- a/pkg2zip.c +++ b/pkg2zip.c @@ -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"); } diff --git a/pkg2zip_psp.c b/pkg2zip_psp.c index 9b6ba89..03b5040 100644 --- a/pkg2zip_psp.c +++ b/pkg2zip_psp.c @@ -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); diff --git a/pkg2zip_sys.c b/pkg2zip_sys.c index 08ed89d..dedce2d 100644 --- a/pkg2zip_sys.c +++ b/pkg2zip_sys.c @@ -11,6 +11,64 @@ #define WIN32_LEAN_AND_MEAN #include +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 #include +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; diff --git a/pkg2zip_sys.h b/pkg2zip_sys.h index 5f48a5e..6400895 100644 --- a/pkg2zip_sys.h +++ b/pkg2zip_sys.h @@ -1,7 +1,11 @@ #pragma once -#include -#include +#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; diff --git a/pkg2zip_utils.c b/pkg2zip_utils.c deleted file mode 100644 index 5e24fae..0000000 --- a/pkg2zip_utils.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "pkg2zip_utils.h" - -#include -#include -#include - -void fatal(const char* msg, ...) -{ - va_list args; - va_start(args, msg); - vfprintf(stderr, msg, args); - va_end(args); - - exit(EXIT_FAILURE); -} diff --git a/pkg2zip_utils.h b/pkg2zip_utils.h index f11444e..695dcda 100644 --- a/pkg2zip_utils.h +++ b/pkg2zip_utils.h @@ -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; diff --git a/pkg2zip_zip.c b/pkg2zip_zip.c index d5f9edb..d32d324 100644 --- a/pkg2zip_zip.c +++ b/pkg2zip_zip.c @@ -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); diff --git a/pkg2zip_zrif.c b/pkg2zip_zrif.c index 2a81cbc..cfaf48b 100644 --- a/pkg2zip_zrif.c +++ b/pkg2zip_zrif.c @@ -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);