diff options
author | Joshua Hill | 2010-05-25 00:25:02 -0400 |
---|---|---|
committer | Joshua Hill | 2010-05-25 00:25:02 -0400 |
commit | 507825f0130fec6d148f6177a11833321ffc7fce (patch) | |
tree | 97dafd8d98d0e89b49cb8724075f65f6c93fef11 | |
parent | 9457cfd1b496e1e5ba48d1b387a040e9402ed80b (diff) | |
download | idevicerestore-507825f0130fec6d148f6177a11833321ffc7fce.tar.gz idevicerestore-507825f0130fec6d148f6177a11833321ffc7fce.tar.bz2 |
Filesystem is now restoring, need to add in kernelcache restore and nor restore and everything should be good.
Note: The latest HEAD from marcan's usbmuxd is required for this program to work. Linux kernel drivers do some wacky stuff with iPod audio interfaces
-rw-r--r-- | src/idevicerestore.c | 201 | ||||
-rw-r--r-- | src/ipsw.c | 133 | ||||
-rw-r--r-- | src/ipsw.h | 2 |
3 files changed, 195 insertions, 141 deletions
diff --git a/src/idevicerestore.c b/src/idevicerestore.c index d6551a4..27cc161 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -100,7 +100,7 @@ int main(int argc, char* argv[]) { lockdownd_error_t lockdown_error = LOCKDOWN_E_SUCCESS; info("Checking for device in normal mode...\n"); - device_error = idevice_new(&device, uuid); + device_error = 1;//idevice_new(&device, uuid); if (device_error != IDEVICE_E_SUCCESS) { info("Checking for the device in recovery mode...\n"); recovery_error = irecv_open(&recovery); @@ -164,16 +164,16 @@ int main(int argc, char* argv[]) { return -1; } + int buildmanifest_size = 0; + char* buildmanifest_data = NULL; info("Extracting BuildManifest.plist from IPSW\n"); - ipsw_file* buildmanifest = ipsw_extract_file(ipsw, "BuildManifest.plist"); - if (buildmanifest == NULL) { + if (ipsw_extract_to_memory(ipsw, "BuildManifest.plist", &buildmanifest_data, &buildmanifest_size) < 0) { error("ERROR: Unable to extract BuildManifest.plist IPSW\n"); return -1; } plist_t manifest = NULL; - plist_from_xml(buildmanifest->data, buildmanifest->size, &manifest); - ipsw_free_file(buildmanifest); + plist_from_xml(buildmanifest_data, buildmanifest_size, &manifest); info("Creating TSS request\n"); plist_t tss_request = tss_create_request(manifest, ecid); @@ -196,21 +196,21 @@ int main(int argc, char* argv[]) { // Get name of filesystem DMG in IPSW char* filesystem = NULL; plist_t filesystem_node = plist_dict_get_item(tss_request, "OS"); - if(!filesystem_node || plist_get_node_type(filesystem_node) != PLIST_DICT) { + if (!filesystem_node || plist_get_node_type(filesystem_node) != PLIST_DICT) { error("ERROR: Unable to find OS filesystem\n"); plist_free(tss_request); return -1; } plist_t filesystem_info_node = plist_dict_get_item(filesystem_node, "Info"); - if(!filesystem_info_node || plist_get_node_type(filesystem_info_node) != PLIST_DICT) { + if (!filesystem_info_node || plist_get_node_type(filesystem_info_node) != PLIST_DICT) { error("ERROR: Unable to find filesystem info node\n"); plist_free(tss_request); return -1; } plist_t filesystem_info_path_node = plist_dict_get_item(filesystem_info_node, "Path"); - if(!filesystem_info_path_node || plist_get_node_type(filesystem_info_path_node) != PLIST_STRING) { + if (!filesystem_info_path_node || plist_get_node_type(filesystem_info_path_node) != PLIST_STRING) { error("ERROR: Unable to find filesystem info path node\n"); plist_free(tss_request); return -1; @@ -218,6 +218,12 @@ int main(int argc, char* argv[]) { plist_get_string_val(filesystem_info_path_node, &filesystem); plist_free(tss_request); + info("Extracting filesystem from IPSW\n"); + if(ipsw_extract_to_file(ipsw, filesystem, filesystem) < 0) { + error("ERROR: Unable to extract filesystem\n"); + return -1; + } + if (idevicerestore_mode == NORMAL_MODE) { // Place the device in recovery mode info("Entering recovery mode...\n"); @@ -286,19 +292,24 @@ int main(int argc, char* argv[]) { return -1; } - idevice_event_subscribe(&device_callback, NULL); + //idevice_event_subscribe(&device_callback, NULL); info("Waiting for device to enter restore mode\n"); - while(idevicerestore_mode != RESTORE_MODE) sleep(1); - device_error = idevice_new(&device, uuid); - if (device_error != IDEVICE_E_SUCCESS) { - error("ERROR: Unable to open device\n"); - plist_free(tss_response); - return -1; + while (idevicerestore_mode != RESTORE_MODE) { + device_error = idevice_new(&device, uuid); + if (device_error == IDEVICE_E_SUCCESS) { + idevicerestore_mode = RESTORE_MODE; + break; + } + sleep(2); + info("Got response %d\n", device_error); + info("Retrying connection...\n"); + //plist_free(tss_response); + //return -1; } - + idevice_set_debug_level(5); restored_client_t restore = NULL; restored_error_t restore_error = restored_client_new(device, &restore, "idevicerestore"); - if(restore_error != RESTORE_E_SUCCESS) { + if (restore_error != RESTORE_E_SUCCESS) { error("ERROR: Unable to start restored client\n"); plist_free(tss_response); idevice_free(device); @@ -329,38 +340,32 @@ int main(int argc, char* argv[]) { if (msgtype_node && PLIST_STRING == plist_get_node_type(msgtype_node)) { char *msgtype = NULL; plist_get_string_val(msgtype_node, &msgtype); - if(!strcmp(msgtype, "ProgressMsg")) { + if (!strcmp(msgtype, "ProgressMsg")) { restore_error = progress_msg(restore, message); - } - else if(!strcmp(msgtype, "DataRequestMsg")) { + } else if (!strcmp(msgtype, "DataRequestMsg")) { //restore_error = data_request_msg(device, restore, message, filesystem); plist_t datatype_node = plist_dict_get_item(message, "DataType"); if (datatype_node && PLIST_STRING == plist_get_node_type(datatype_node)) { char *datatype = NULL; plist_get_string_val(datatype_node, &datatype); - if(!strcmp(datatype, "SystemImageData")) { + if (!strcmp(datatype, "SystemImageData")) { send_system_data(device, restore, filesystem); - } - else if(!strcmp(datatype, "KernelCache")) { + } else if (!strcmp(datatype, "KernelCache")) { send_kernel_data(device, restore, kernelcache); - } - else if(!strcmp(datatype, "NORData")) { + } else if (!strcmp(datatype, "NORData")) { send_nor_data(device, restore); - } - else { + } else { // Unknown DataType!! error("Unknown DataType\n"); return -1; } } - } - else if(!strcmp(msgtype, "StatusMsg")) { + } else if (!strcmp(msgtype, "StatusMsg")) { restore_error = status_msg(restore, message); - } - else { + } else { printf("Received unknown message type: %s\n", msgtype); } } @@ -382,7 +387,7 @@ int main(int argc, char* argv[]) { } void device_callback(const idevice_event_t* event, void *user_data) { - if(event->event == IDEVICE_DEVICE_ADD) { + if (event->event == IDEVICE_DEVICE_ADD) { idevicerestore_mode = RESTORE_MODE; } } @@ -411,16 +416,13 @@ int data_request_msg(idevice_t device, restored_client_t client, plist_t msg, co if (datatype_node && PLIST_STRING == plist_get_node_type(datatype_node)) { char *datatype = NULL; plist_get_string_val(datatype_node, &datatype); - if(!strcmp(datatype, "SystemImageData")) { + if (!strcmp(datatype, "SystemImageData")) { send_system_data(device, client, filesystem); - } - else if(!strcmp(datatype, "KernelCache")) { + } else if (!strcmp(datatype, "KernelCache")) { send_kernel_data(device, client, kernel); - } - else if(!strcmp(datatype, "NORData")) { + } else if (!strcmp(datatype, "NORData")) { send_nor_data(device, client); - } - else { + } else { // Unknown DataType!! error("Unknown DataType\n"); return -1; @@ -442,21 +444,21 @@ int send_system_data(idevice_t device, restored_client_t client, const char *fil idevice_connection_t connection = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; - for(i = 0; i < 5; i++) { + for (i = 0; i < 5; i++) { ret = idevice_connect(device, ASR_PORT, &connection); - if(ret == IDEVICE_E_SUCCESS) + if (ret == IDEVICE_E_SUCCESS) break; else sleep(1); } - if(ret != IDEVICE_E_SUCCESS) + if (ret != IDEVICE_E_SUCCESS) return ret; memset(buffer, '\0', 0x1000); - ret = idevice_connection_receive(connection, buffer, 0x1000, &recv_bytes); - if(ret != IDEVICE_E_SUCCESS) { + ret = idevice_connection_receive(connection, buffer, 0x1000, &recv_bytes); + if (ret != IDEVICE_E_SUCCESS) { idevice_disconnect(connection); return ret; } @@ -464,7 +466,7 @@ int send_system_data(idevice_t device, restored_client_t client, const char *fil printf("%s", buffer); FILE* fd = fopen(filesystem, "rb"); - if(fd == NULL) { + if (fd == NULL) { idevice_disconnect(connection); return ret; } @@ -493,7 +495,7 @@ int send_system_data(idevice_t device, restored_client_t client, const char *fil plist_to_xml(dict, &xml, &dict_size); ret = idevice_connection_send(connection, xml, dict_size, &sent_bytes); - if(ret != IDEVICE_E_SUCCESS) { + if (ret != IDEVICE_E_SUCCESS) { idevice_disconnect(connection); return ret; } @@ -507,7 +509,7 @@ int send_system_data(idevice_t device, restored_client_t client, const char *fil do { memset(buffer, '\0', 0x1000); ret = idevice_connection_receive(connection, buffer, 0x1000, &recv_bytes); - if(ret != IDEVICE_E_SUCCESS) { + if (ret != IDEVICE_E_SUCCESS) { idevice_disconnect(connection); return ret; } @@ -519,7 +521,7 @@ int send_system_data(idevice_t device, restored_client_t client, const char *fil plist_t command_node = plist_dict_get_item(request, "Command"); if (command_node && PLIST_STRING == plist_get_node_type(command_node)) { plist_get_string_val(command_node, &command); - if(!strcmp(command, "OOBData")) { + if (!strcmp(command, "OOBData")) { plist_t oob_length_node = plist_dict_get_item(request, "OOB Length"); if (!oob_length_node || PLIST_UINT != plist_get_node_type(oob_length_node)) { printf("Error fetching OOB Length\n"); @@ -539,14 +541,14 @@ int send_system_data(idevice_t device, restored_client_t client, const char *fil plist_get_uint_val(oob_offset_node, &oob_offset); char* oob_data = (char*) malloc(oob_length); - if(oob_data == NULL) { + if (oob_data == NULL) { error("Out of memory\n"); idevice_disconnect(connection); return IDEVICE_E_UNKNOWN_ERROR; } fseek(fd, oob_offset, SEEK_SET); - if(fread(oob_data, 1, oob_length, fd) != oob_length) { + if (fread(oob_data, 1, oob_length, fd) != oob_length) { error("Unable to read filesystem offset\n"); idevice_disconnect(connection); free(oob_data); @@ -554,7 +556,7 @@ int send_system_data(idevice_t device, restored_client_t client, const char *fil } ret = idevice_connection_send(connection, oob_data, oob_length, &sent_bytes); - if(sent_bytes != oob_length || ret != IDEVICE_E_SUCCESS) { + if (sent_bytes != oob_length || ret != IDEVICE_E_SUCCESS) { printf("Unable to send %d bytes to asr\n", sent_bytes); idevice_disconnect(connection); free(oob_data); @@ -565,17 +567,17 @@ int send_system_data(idevice_t device, restored_client_t client, const char *fil } } - } while(strcmp(command, "Payload")); + } while (strcmp(command, "Payload")); fseek(fd, 0, SEEK_SET); char data[1450]; - for(i = len; i > 0; i -= 1450) { + for (i = len; i > 0; i -= 1450) { int size = 1450; - if(i < 1450) { + if (i < 1450) { size = i; } - if(fread(data, 1, size, fd) != (unsigned int)size) { + if (fread(data, 1, size, fd) != (unsigned int) size) { fclose(fd); idevice_disconnect(connection); printf("Error reading filesystem\n"); @@ -583,11 +585,11 @@ int send_system_data(idevice_t device, restored_client_t client, const char *fil } ret = idevice_connection_send(connection, data, size, &sent_bytes); - if(ret != IDEVICE_E_SUCCESS) { + if (ret != IDEVICE_E_SUCCESS) { fclose(fd); } - if(i % (1450*1000) == 0) { + if (i % (1450 * 1000) == 0) { printf("."); } } @@ -601,7 +603,7 @@ int send_system_data(idevice_t device, restored_client_t client, const char *fil int send_kernel_data(idevice_t device, restored_client_t client, const char *kernel) { printf("Sending kernelcache\n"); FILE* fd = fopen(kernel, "rb"); - if(fd == NULL) { + if (fd == NULL) { info("Unable to open kernelcache"); return -1; } @@ -611,13 +613,13 @@ int send_kernel_data(idevice_t device, restored_client_t client, const char *ker fseek(fd, 0, SEEK_SET); char* kernel_data = (char*) malloc(len); - if(kernel_data == NULL) { + if (kernel_data == NULL) { error("Unable to allocate memory for kernel data"); fclose(fd); return -1; } - if(fread(kernel_data, 1, len, fd) != len) { + if (fread(kernel_data, 1, len, fd) != len) { error("Unable to read kernel data\n"); free(kernel_data); fclose(fd); @@ -631,7 +633,7 @@ int send_kernel_data(idevice_t device, restored_client_t client, const char *ker plist_dict_insert_item(dict, "KernelCacheFile", kernelcache_node); restored_error_t ret = restored_send(client, dict); - if(ret != RESTORE_E_SUCCESS) { + if (ret != RESTORE_E_SUCCESS) { error("Unable to send kernelcache data\n"); free(kernel_data); plist_free(dict); @@ -644,7 +646,6 @@ int send_kernel_data(idevice_t device, restored_client_t client, const char *ker return 0; } - int send_nor_data(idevice_t device, restored_client_t client) { info("Not implemented\n"); return 0; @@ -734,9 +735,10 @@ int send_ibec(char* ipsw, plist_t tss) { return -1; } + int ibec_size = 0; + char* ibec_data = NULL; info("Extracting %s from %s\n", path, ipsw); - ipsw_file* ibec = ipsw_extract_file(ipsw, path); - if (ibec == NULL) { + if (ipsw_extract_to_memory(ipsw, path, &ibec_data, &ibec_size)) { error("ERROR: Unable to extract %s from %s\n", path, ipsw); irecv_close(client); client = NULL; @@ -745,19 +747,19 @@ int send_ibec(char* ipsw, plist_t tss) { return -1; } - img3_file* img3 = img3_parse_file(ibec->data, ibec->size); + img3_file* img3 = img3_parse_file(ibec_data, ibec_size); if (img3 == NULL) { error("ERROR: Unable to parse IMG3: %s\n", path); - ipsw_free_file(ibec); irecv_close(client); client = NULL; + free(ibec_data); free(path); free(blob); return -1; } - if (ibec) { - ipsw_free_file(ibec); - ibec = NULL; + if (ibec_data) { + free(ibec_data); + ibec_data = NULL; } if (img3_replace_signature(img3, blob) < 0) { @@ -863,9 +865,10 @@ int send_applelogo(char* ipsw, plist_t tss) { return -1; } + int applelogo_size = 0; + char* applelogo_data = NULL; info("Extracting %s from %s\n", path, ipsw); - ipsw_file* applelogo = ipsw_extract_file(ipsw, path); - if (applelogo == NULL) { + if (ipsw_extract_to_memory(ipsw, path, &applelogo_data, &applelogo_size) < 0) { error("ERROR: Unable to extract %s from %s\n", path, ipsw); irecv_close(client); client = NULL; @@ -874,19 +877,19 @@ int send_applelogo(char* ipsw, plist_t tss) { return -1; } - img3_file* img3 = img3_parse_file(applelogo->data, applelogo->size); + img3_file* img3 = img3_parse_file(applelogo_data, applelogo_size); if (img3 == NULL) { error("ERROR: Unable to parse IMG3: %s\n", path); - ipsw_free_file(applelogo); irecv_close(client); client = NULL; + free(applelogo_data); free(path); free(blob); return -1; } - if (applelogo) { - ipsw_free_file(applelogo); - applelogo = NULL; + if (applelogo_data) { + free(applelogo_data); + applelogo_data = NULL; } if (img3_replace_signature(img3, blob) < 0) { @@ -993,9 +996,10 @@ int send_devicetree(char* ipsw, plist_t tss) { return -1; } + int devicetree_size = 0; + char* devicetree_data = NULL; info("Extracting %s from %s\n", path, ipsw); - ipsw_file* devicetree = ipsw_extract_file(ipsw, path); - if (devicetree == NULL) { + if (ipsw_extract_to_memory(ipsw, path, &devicetree_data, &devicetree_size) < 0) { error("ERROR: Unable to extract %s from %s\n", path, ipsw); irecv_close(client); client = NULL; @@ -1004,19 +1008,19 @@ int send_devicetree(char* ipsw, plist_t tss) { return -1; } - img3_file* img3 = img3_parse_file(devicetree->data, devicetree->size); + img3_file* img3 = img3_parse_file(devicetree_data, devicetree_size); if (img3 == NULL) { error("ERROR: Unable to parse IMG3: %s\n", path); - ipsw_free_file(devicetree); + free(devicetree_data); irecv_close(client); client = NULL; free(path); free(blob); return -1; } - if (devicetree) { - ipsw_free_file(devicetree); - devicetree = NULL; + if (devicetree_data) { + free(devicetree_data); + devicetree_data = NULL; } if (img3_replace_signature(img3, blob) < 0) { @@ -1122,9 +1126,10 @@ int send_ramdisk(char* ipsw, plist_t tss) { return -1; } + int ramdisk_size = 0; + char* ramdisk_data = NULL; info("Extracting %s from %s\n", path, ipsw); - ipsw_file* ramdisk = ipsw_extract_file(ipsw, path); - if (ramdisk == NULL) { + if (ipsw_extract_to_memory(ipsw, path, &ramdisk_data, &ramdisk_size) < 0) { error("ERROR: Unable to extract %s from %s\n", path, ipsw); irecv_close(client); client = NULL; @@ -1133,19 +1138,19 @@ int send_ramdisk(char* ipsw, plist_t tss) { return -1; } - img3_file* img3 = img3_parse_file(ramdisk->data, ramdisk->size); + img3_file* img3 = img3_parse_file(ramdisk_data, ramdisk_size); if (img3 == NULL) { error("ERROR: Unable to parse IMG3: %s\n", path); - ipsw_free_file(ramdisk); + free(ramdisk_data); irecv_close(client); client = NULL; free(path); free(blob); return -1; } - if (ramdisk) { - ipsw_free_file(ramdisk); - ramdisk = NULL; + if (ramdisk_data) { + free(ramdisk_data); + ramdisk_data = NULL; } if (img3_replace_signature(img3, blob) < 0) { @@ -1251,9 +1256,10 @@ int send_kernelcache(char* ipsw, plist_t tss) { return -1; } + int kernelcache_size = 0; + char* kernelcache_data = NULL; info("Extracting %s from %s\n", path, ipsw); - ipsw_file* kernelcache = ipsw_extract_file(ipsw, path); - if (kernelcache == NULL) { + if (ipsw_extract_to_memory(ipsw, path, &kernelcache_data, &kernelcache_size) < 0) { error("ERROR: Unable to extract %s from %s\n", path, ipsw); irecv_close(client); client = NULL; @@ -1262,19 +1268,19 @@ int send_kernelcache(char* ipsw, plist_t tss) { return -1; } - img3_file* img3 = img3_parse_file(kernelcache->data, kernelcache->size); + img3_file* img3 = img3_parse_file(kernelcache_data, kernelcache_size); if (img3 == NULL) { error("ERROR: Unable to parse IMG3: %s\n", path); - ipsw_free_file(kernelcache); + free(kernelcache_data); irecv_close(client); client = NULL; free(path); free(blob); return -1; } - if (kernelcache) { - ipsw_free_file(kernelcache); - kernelcache = NULL; + if (kernelcache_data) { + free(kernelcache_data); + kernelcache_data = NULL; } if (img3_replace_signature(img3, blob) < 0) { @@ -1344,6 +1350,7 @@ int send_kernelcache(char* ipsw, plist_t tss) { } if (client) { + irecv_set_configuration(client, 4); irecv_close(client); client = NULL; } @@ -26,6 +26,8 @@ #include "ipsw.h" #include "idevicerestore.h" +#define BUFSIZE 0x100000 + typedef struct { struct zip* zip; } ipsw_archive; @@ -36,13 +38,13 @@ void ipsw_close(ipsw_archive* archive); ipsw_archive* ipsw_open(const char* ipsw) { int err = 0; ipsw_archive* archive = (ipsw_archive*) malloc(sizeof(ipsw_archive)); - if(archive == NULL) { + if (archive == NULL) { error("ERROR: Out of memory\n"); return NULL; } archive->zip = zip_open(ipsw, 0, &err); - if(archive->zip == NULL) { + if (archive->zip == NULL) { error("ERROR: zip_open: %s: %d\n", ipsw, err); free(archive); return NULL; @@ -51,76 +53,121 @@ ipsw_archive* ipsw_open(const char* ipsw) { return archive; } -ipsw_file* ipsw_extract_file(const char* ipsw, const char* filename) { +int ipsw_extract_to_file(const char* ipsw, const char* infile, const char* outfile) { ipsw_archive* archive = ipsw_open(ipsw); - if(archive == NULL || archive->zip == NULL) { + if (archive == NULL || archive->zip == NULL) { error("ERROR: Invalid archive\n"); - return NULL; + return -1; } - int zindex = zip_name_locate(archive->zip, filename, 0); - if(zindex < 0) { - error("ERROR: zip_name_locate: %s\n", filename); - return NULL; + int zindex = zip_name_locate(archive->zip, infile, 0); + if (zindex < 0) { + error("ERROR: zip_name_locate: %s\n", infile); + return -1; } struct zip_stat zstat; zip_stat_init(&zstat); - if(zip_stat_index(archive->zip, zindex, 0, &zstat) != 0) { - error("ERROR: zip_stat_index: %s\n", filename); - return NULL; + if (zip_stat_index(archive->zip, zindex, 0, &zstat) != 0) { + error("ERROR: zip_stat_index: %s\n", infile); + return -1; + } + + char* buffer = (char*) malloc(BUFSIZE); + if(buffer == NULL) { + error("ERROR: Unable to allocate memory\n"); + return -1; } struct zip_file* zfile = zip_fopen_index(archive->zip, zindex, 0); - if(zfile == NULL) { - error("ERROR: zip_fopen_index: %s\n", filename); - return NULL; + if (zfile == NULL) { + error("ERROR: zip_fopen_index: %s\n", infile); + return -1; } - ipsw_file* file = (ipsw_file*) malloc(sizeof(ipsw_file)); - if(file == NULL) { - error("ERROR: Out of memory\n"); + FILE* fd = fopen(outfile, "wb"); + if(fd == NULL) { + error("ERROR: Unable to open output file: %s\n", outfile); zip_fclose(zfile); - return NULL; + return -1; } - file->size = zstat.size; - file->index = zstat.index; - file->name = strdup(zstat.name); - file->data = (unsigned char*) malloc(file->size); - if(file->data == NULL) { + int i = 0; + int size = 0; + int count = 0; + for (i = zstat.size; i > 0; i -= count) { + if(i < BUFSIZE) size = i; + else size = BUFSIZE; + count = zip_fread(zfile, buffer, size); + if (count < 0) { + error("ERROR: zip_fread: %s\n", infile); + zip_fclose(zfile); + free(buffer); + return -1; + } + fwrite(buffer, 1, count, fd); + debug("."); + } + debug("\n"); + + fclose(fd); + zip_fclose(zfile); + ipsw_close(archive); + free(buffer); + return 0; +} + +int ipsw_extract_to_memory(const char* ipsw, const char* infile, char** pbuffer, int* psize) { + ipsw_archive* archive = ipsw_open(ipsw); + if (archive == NULL || archive->zip == NULL) { + error("ERROR: Invalid archive\n"); + return -1; + } + + int zindex = zip_name_locate(archive->zip, infile, 0); + if (zindex < 0) { + error("ERROR: zip_name_locate: %s\n", infile); + return -1; + } + + struct zip_stat zstat; + zip_stat_init(&zstat); + if (zip_stat_index(archive->zip, zindex, 0, &zstat) != 0) { + error("ERROR: zip_stat_index: %s\n", infile); + return -1; + } + + struct zip_file* zfile = zip_fopen_index(archive->zip, zindex, 0); + if (zfile == NULL) { + error("ERROR: zip_fopen_index: %s\n", infile); + return -1; + } + + int size = zstat.size; + char* buffer = (unsigned char*) malloc(size); + if (buffer == NULL) { error("ERROR: Out of memory\n"); - ipsw_free_file(file); zip_fclose(zfile); - return NULL; + return -1; } - if(zip_fread(zfile, file->data, file->size) != file->size) { - error("ERROR: zip_fread: %s\n", filename); - ipsw_free_file(file); + if (zip_fread(zfile, buffer, size) != size) { + error("ERROR: zip_fread: %s\n", infile); zip_fclose(zfile); - return NULL; + free(buffer); + return -1; } zip_fclose(zfile); ipsw_close(archive); - return file; -} -void ipsw_free_file(ipsw_file* file) { - if(file != NULL) { - if(file->name != NULL) { - free(file->name); - } - if(file->data != NULL) { - free(file->data); - } - free(file); - } + *pbuffer = buffer; + *psize = size; + return 0; } void ipsw_close(ipsw_archive* archive) { - if(archive != NULL) { + if (archive != NULL) { zip_unchange_all(archive->zip); zip_close(archive->zip); free(archive); @@ -31,7 +31,7 @@ typedef struct { unsigned char* data; } ipsw_file; -ipsw_file* ipsw_extract_file(const char* ipsw, const char* filename); +int ipsw_extract_to_memory(const char* ipsw, const char* infile, char** pbuffer, int* psize); void ipsw_free_file(ipsw_file* file); #endif |