diff --git a/file.c b/file.c index 58be87d..9024dc7 100644 --- a/file.c +++ b/file.c @@ -39,6 +39,27 @@ static char *mount_points[] = { #define N_MOUNT_POINTS (sizeof(mount_points) / sizeof(char **)) +int allocateReadFile(char *file, void **buffer) { + SceUID fd = sceIoOpen(file, SCE_O_RDONLY, 0); + if (fd < 0) + return fd; + + int off = sceIoLseek32(fd, 0, SCE_SEEK_CUR); + int size = sceIoLseek32(fd, 0, SCE_SEEK_END); + sceIoLseek(fd, off, SCE_SEEK_SET); + + *buffer = malloc(size); + if (!*buffer) { + sceIoClose(fd); + return -1; + } + + int read = sceIoRead(fd, *buffer, size); + sceIoClose(fd); + + return read; +} + int ReadFile(char *file, void *buf, int size) { SceUID fd = sceIoOpen(file, SCE_O_RDONLY, 0); if (fd < 0) diff --git a/file.h b/file.h index 61ce4c2..c20e798 100644 --- a/file.h +++ b/file.h @@ -69,6 +69,7 @@ typedef struct { int folders; } FileList; +int allocateReadFile(char *file, void **buffer); int ReadFile(char *file, void *buf, int size); int WriteFile(char *file, void *buf, int size); diff --git a/package_installer.c b/package_installer.c index 437e3ea..89641f7 100644 --- a/package_installer.c +++ b/package_installer.c @@ -81,51 +81,6 @@ int promote(char *path) { return result; } -char *get_title_id(const char *filename) { - char *res = NULL; - long size = 0; - FILE *fin = NULL; - char *buf = NULL; - int i; - - SfoHeader *header; - SfoEntry *entry; - - fin = fopen(filename, "rb"); - if (!fin) - goto cleanup; - if (fseek(fin, 0, SEEK_END) != 0) - goto cleanup; - if ((size = ftell(fin)) == -1) - goto cleanup; - if (fseek(fin, 0, SEEK_SET) != 0) - goto cleanup; - buf = calloc(1, size + 1); - if (!buf) - goto cleanup; - if (fread(buf, size, 1, fin) != 1) - goto cleanup; - - header = (SfoHeader*)buf; - entry = (SfoEntry*)(buf + sizeof(SfoHeader)); - for (i = 0; i < header->count; ++i, ++entry) { - const char *name = buf + header->keyofs + entry->nameofs; - const char *value = buf + header->valofs + entry->dataofs; - if (name >= buf + size || value >= buf + size) - break; - if (strcmp(name, "TITLE_ID") == 0) - res = strdup(value); - } - -cleanup: - if (buf) - free(buf); - if (fin) - fclose(fin); - - return res; -} - void fpkg_hmac(const uint8_t *data, unsigned int len, uint8_t hmac[16]) { SHA1_CTX ctx; uint8_t sha1[20]; @@ -163,18 +118,31 @@ int makeHeadBin() { if (sceIoGetstat(HEAD_BIN, &stat) >= 0) return -1; + // Read param.sfo + void *sfo_buffer = NULL; + int res = allocateReadFile(PACKAGE_DIR "/sce_sys/param.sfo", &sfo_buffer); + if (res < 0) + return res; + // Get title id - char *title_id = get_title_id(PACKAGE_DIR "/sce_sys/param.sfo"); - if (!title_id)// || strlen(title_id) != 9) // Enforce TITLEID format? + char titleid[12]; + getSfoString(sfo_buffer, "TITLE_ID", titleid, sizeof(titleid)); + if (strlen(titleid) != 9) // Enforce TITLE_ID format return -2; + // Free sfo buffer + free(sfo_buffer); + + // TODO: check category for update installation + // TODO: use real content_id + // Allocate head.bin buffer uint8_t *head_bin = malloc(sizeof(base_head_bin)); memcpy(head_bin, base_head_bin, sizeof(base_head_bin)); // Write full titleid char full_title_id[128]; - snprintf(full_title_id, sizeof(full_title_id), "EP9000-%s_00-XXXXXXXXXXXXXXXX", title_id); + snprintf(full_title_id, sizeof(full_title_id), "EP9000-%s_00-XXXXXXXXXXXXXXXX", titleid); strncpy((char *)&head_bin[0x30], full_title_id, 48); // hmac of pkg header @@ -201,7 +169,6 @@ int makeHeadBin() { WriteFile(HEAD_BIN, head_bin, sizeof(base_head_bin)); free(head_bin); - free(title_id); return 0; } diff --git a/sfo.c b/sfo.c index 34e4047..4ded74a 100644 --- a/sfo.c +++ b/sfo.c @@ -27,6 +27,38 @@ #include "utils.h" #include "sfo.h" +int getSfoValue(void *buffer, char *name, uint32_t *value) { + SfoHeader *header = (SfoHeader *)buffer; + SfoEntry *entries = (SfoEntry *)((uint32_t)buffer + sizeof(SfoHeader)); + + int i; + for (i = 0; i < header->count; i++) { + if (strcmp(buffer + header->keyofs + entries[i].nameofs, name) == 0) { + *value = *(uint32_t *)(buffer + header->valofs + entries[i].dataofs); + return 0; + } + } + + return -1; +} + +int getSfoString(void *buffer, char *name, char *string, int length) { + SfoHeader *header = (SfoHeader *)buffer; + SfoEntry *entries = (SfoEntry *)((uint32_t)buffer + sizeof(SfoHeader)); + + int i; + for (i = 0; i < header->count; i++) { + if (strcmp(buffer + header->keyofs + entries[i].nameofs, name) == 0) { + memset(string, 0, length); + strncpy(string, buffer + header->valofs + entries[i].dataofs, length); + string[length - 1] = '\0'; + return 0; + } + } + + return -1; +} + int SFOReader(char *file) { uint8_t *buffer = malloc(BIG_BUFFER_SIZE); if (!buffer) diff --git a/sfo.h b/sfo.h index 1ff3cb7..fc953aa 100644 --- a/sfo.h +++ b/sfo.h @@ -45,6 +45,9 @@ typedef struct SfoEntry { uint32_t dataofs; } __attribute__((packed)) SfoEntry; +int getSfoValue(void *buffer, char *name, uint32_t *value); +int getSfoString(void *buffer, char *name, char *string, int length); + int SFOReader(char *file); #endif \ No newline at end of file