summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Joshua Hill2010-05-25 00:25:02 -0400
committerGravatar Joshua Hill2010-05-25 00:25:02 -0400
commit507825f0130fec6d148f6177a11833321ffc7fce (patch)
tree97dafd8d98d0e89b49cb8724075f65f6c93fef11 /src
parent9457cfd1b496e1e5ba48d1b387a040e9402ed80b (diff)
downloadidevicerestore-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
Diffstat (limited to 'src')
-rw-r--r--src/idevicerestore.c201
-rw-r--r--src/ipsw.c133
-rw-r--r--src/ipsw.h2
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;
}
diff --git a/src/ipsw.c b/src/ipsw.c
index 56fd216..f602d16 100644
--- a/src/ipsw.c
+++ b/src/ipsw.c
@@ -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);
diff --git a/src/ipsw.h b/src/ipsw.h
index 6a49937..f764611 100644
--- a/src/ipsw.h
+++ b/src/ipsw.h
@@ -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