summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/asr.c56
-rw-r--r--src/asr.h9
-rw-r--r--src/common.h6
-rw-r--r--src/idevicerestore.c195
-rw-r--r--src/idevicerestore.h7
-rw-r--r--src/ipsw.c269
-rw-r--r--src/ipsw.h43
-rw-r--r--src/restore.c35
-rw-r--r--src/restore.h7
9 files changed, 272 insertions, 355 deletions
diff --git a/src/asr.c b/src/asr.c
index a1aba76..b2aeaf5 100644
--- a/src/asr.c
+++ b/src/asr.c
@@ -43,6 +43,7 @@
#include "asr.h"
#include "idevicerestore.h"
#include "common.h"
+#include "ipsw.h"
#define ASR_VERSION 1
#define ASR_STREAM_ID 1
@@ -205,9 +206,8 @@ void asr_free(asr_client_t asr)
}
}
-int asr_perform_validation(asr_client_t asr, const char* filesystem)
+int asr_perform_validation(asr_client_t asr, ipsw_file_handle_t file)
{
- FILE* file = NULL;
uint64_t length = 0;
char* command = NULL;
plist_t node = NULL;
@@ -216,20 +216,9 @@ int asr_perform_validation(asr_client_t asr, const char* filesystem)
plist_t payload_info = NULL;
int attempts = 0;
- file = fopen(filesystem, "rb");
- if (file == NULL) {
- return -1;
- }
-
-#ifdef WIN32
- length = _lseeki64(fileno(file), 0, SEEK_END);
- _lseeki64(fileno(file), 0, SEEK_SET);
- rewind(file);
-#else
- fseeko(file, 0, SEEK_END);
- length = ftello(file);
- fseeko(file, 0, SEEK_SET);
-#endif
+ ipsw_file_seek(file, 0, SEEK_END);
+ length = ipsw_file_tell(file);
+ ipsw_file_seek(file, 0, SEEK_SET);
payload_info = plist_new_dict();
plist_dict_set_item(payload_info, "Port", plist_new_uint(1));
@@ -296,7 +285,7 @@ int asr_perform_validation(asr_client_t asr, const char* filesystem)
return 0;
}
-int asr_handle_oob_data_request(asr_client_t asr, plist_t packet, FILE* file)
+int asr_handle_oob_data_request(asr_client_t asr, plist_t packet, ipsw_file_handle_t file)
{
char* oob_data = NULL;
uint64_t oob_offset = 0;
@@ -324,13 +313,8 @@ int asr_handle_oob_data_request(asr_client_t asr, plist_t packet, FILE* file)
return -1;
}
-#ifdef WIN32
- rewind(file);
- _lseeki64(fileno(file), oob_offset, SEEK_SET);
-#else
- fseeko(file, oob_offset, SEEK_SET);
-#endif
- if (fread(oob_data, 1, oob_length, file) != oob_length) {
+ ipsw_file_seek(file, oob_offset, SEEK_SET);
+ if (ipsw_file_read(file, oob_data, oob_length) != oob_length) {
error("ERROR: Unable to read OOB data from filesystem offset: %s\n", strerror(errno));
free(oob_data);
return -1;
@@ -345,28 +329,15 @@ int asr_handle_oob_data_request(asr_client_t asr, plist_t packet, FILE* file)
return 0;
}
-int asr_send_payload(asr_client_t asr, const char* filesystem)
+int asr_send_payload(asr_client_t asr, ipsw_file_handle_t file)
{
char *data = NULL;
- FILE* file = NULL;
uint64_t i, length, bytes = 0;
double progress = 0;
- file = fopen(filesystem, "rb");
- if (file == NULL) {
- error("ERROR: Unable to open filesystem image %s: %s\n", filesystem, strerror(errno));
- return -1;
- }
-
-#ifdef WIN32
- length = _lseeki64(fileno(file), 0, SEEK_END);
- _lseeki64(fileno(file), 0, SEEK_SET);
- rewind(file);
-#else
- fseeko(file, 0, SEEK_END);
- length = ftello(file);
- fseeko(file, 0, SEEK_SET);
-#endif
+ ipsw_file_seek(file, 0, SEEK_END);
+ length = ipsw_file_tell(file);
+ ipsw_file_seek(file, 0, SEEK_SET);
data = (char*)malloc(ASR_PAYLOAD_CHUNK_SIZE + 20);
@@ -385,7 +356,7 @@ int asr_send_payload(asr_client_t asr, const char* filesystem)
size = i;
}
- if (fread(data, 1, size, file) != (size_t)size) {
+ if (ipsw_file_read(file, data, size) != (int64_t)size) {
error("Error reading filesystem\n");
retry--;
continue;
@@ -412,6 +383,5 @@ int asr_send_payload(asr_client_t asr, const char* filesystem)
}
free(data);
- fclose(file);
return 0;
}
diff --git a/src/asr.h b/src/asr.h
index b3336a5..0d9534c 100644
--- a/src/asr.h
+++ b/src/asr.h
@@ -41,15 +41,18 @@ struct asr_client {
};
typedef struct asr_client *asr_client_t;
+struct ipsw_file_handle;
+typedef struct ipsw_file_handle* ipsw_file_handle_t;
+
int asr_open_with_timeout(idevice_t device, asr_client_t* asr);
void asr_set_progress_callback(asr_client_t asr, asr_progress_cb_t, void* userdata);
int asr_send(asr_client_t asr, plist_t data);
int asr_receive(asr_client_t asr, plist_t* data);
int asr_send_buffer(asr_client_t asr, const char* data, uint32_t size);
void asr_free(asr_client_t asr);
-int asr_perform_validation(asr_client_t asr, const char* filesystem);
-int asr_send_payload(asr_client_t asr, const char* filesystem);
-int asr_handle_oob_data_request(asr_client_t asr, plist_t packet, FILE* file);
+int asr_perform_validation(asr_client_t asr, ipsw_file_handle_t file);
+int asr_send_payload(asr_client_t asr, ipsw_file_handle_t file);
+int asr_handle_oob_data_request(asr_client_t asr, plist_t packet, ipsw_file_handle_t file);
#ifdef __cplusplus
diff --git a/src/common.h b/src/common.h
index 97d5f96..5afe5ab 100644
--- a/src/common.h
+++ b/src/common.h
@@ -70,6 +70,9 @@ struct dfu_client_t;
struct normal_client_t;
struct restore_client_t;
struct recovery_client_t;
+struct ipsw_archive;
+
+typedef struct ipsw_archive* ipsw_archive_t;
struct idevicerestore_mode_t {
int index;
@@ -101,8 +104,7 @@ struct idevicerestore_client_t {
plist_t preflight_info;
char* udid;
char* srnm;
- char* ipsw;
- const char* filesystem;
+ ipsw_archive_t ipsw;
struct dfu_client_t* dfu;
struct restore_client_t* restore;
struct recovery_client_t* recovery;
diff --git a/src/idevicerestore.c b/src/idevicerestore.c
index 466cfe2..7b69a9f 100644
--- a/src/idevicerestore.c
+++ b/src/idevicerestore.c
@@ -320,6 +320,8 @@ static void irecv_event_cb(const irecv_device_event_t* event, void *userdata)
}
}
+int build_identity_check_components_in_ipsw(plist_t build_identity, ipsw_archive_t ipsw);
+
int idevicerestore_start(struct idevicerestore_client_t* client)
{
int tss_enabled = 0;
@@ -424,7 +426,9 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
download_to_file(s_wtfurl, wtfipsw, 0);
}
- ipsw_extract_to_memory(wtfipsw, wtfname, &wtftmp, &wtfsize);
+ ipsw_archive_t wtf_ipsw = ipsw_open(wtfipsw);
+ ipsw_extract_to_memory(wtf_ipsw, wtfname, &wtftmp, &wtfsize);
+ ipsw_close(wtf_ipsw);
if (!wtftmp) {
error("ERROR: Could not extract WTF\n");
}
@@ -601,12 +605,16 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
char* ipsw = NULL;
res = ipsw_download_fw(fwurl, p_fwsha1, client->cache_dir, &ipsw);
if (res != 0) {
- if (ipsw) {
- free(ipsw);
- }
+ free(ipsw);
return res;
} else {
- client->ipsw = ipsw;
+ client->ipsw = ipsw_open(ipsw);
+ if (!client->ipsw) {
+ error("ERROR: Failed to open ipsw '%s'\n", ipsw);
+ free(ipsw);
+ return -1;
+ }
+ free(ipsw);
}
}
idevicerestore_progress(client, RESTORE_STEP_DETECT, 0.6);
@@ -641,23 +649,17 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
}
}
- // verify if ipsw file exists
- if (access(client->ipsw, F_OK) < 0) {
- error("ERROR: Firmware file %s does not exist.\n", client->ipsw);
- return -1;
- }
-
// extract buildmanifest
if (client->flags & FLAG_CUSTOM) {
info("Extracting Restore.plist from IPSW\n");
if (ipsw_extract_restore_plist(client->ipsw, &client->build_manifest) < 0) {
- error("ERROR: Unable to extract Restore.plist from %s. Firmware file might be corrupt.\n", client->ipsw);
+ error("ERROR: Unable to extract Restore.plist from %s. Firmware file might be corrupt.\n", client->ipsw->path);
return -1;
}
} else {
info("Extracting BuildManifest from IPSW\n");
if (ipsw_extract_build_manifest(client->ipsw, &client->build_manifest, &tss_enabled) < 0) {
- error("ERROR: Unable to extract BuildManifest from %s. Firmware file might be corrupt.\n", client->ipsw);
+ error("ERROR: Unable to extract BuildManifest from %s. Firmware file might be corrupt.\n", client->ipsw->path);
return -1;
}
}
@@ -941,115 +943,11 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
/* check if all components we need are actually there */
info("Checking IPSW for required components...\n");
if (build_identity_check_components_in_ipsw(build_identity, client->ipsw) < 0) {
- error("ERROR: Could not find all required components in IPSW %s\n", client->ipsw);
+ error("ERROR: Could not find all required components in IPSW %s\n", client->ipsw->path);
return -1;
}
info("All required components found in IPSW\n");
- // Get filesystem name from build identity
- char* fsname = NULL;
- if (build_identity_get_component_path(build_identity, "OS", &fsname) < 0) {
- error("ERROR: Unable to get path for filesystem component\n");
- return -1;
- }
-
- // check if we already have an extracted filesystem
- int delete_fs = 0;
- char* filesystem = NULL;
- struct stat st;
- memset(&st, '\0', sizeof(struct stat));
- char tmpf[1024];
- if (client->cache_dir) {
- if (stat(client->cache_dir, &st) < 0) {
- mkdir_with_parents(client->cache_dir, 0755);
- }
- strcpy(tmpf, client->cache_dir);
- strcat(tmpf, "/");
- char *ipswtmp = strdup(client->ipsw);
- strcat(tmpf, basename(ipswtmp));
- free(ipswtmp);
- } else {
- strcpy(tmpf, client->ipsw);
- }
-
- if (!ipsw_is_directory(client->ipsw)) {
- // strip off file extension if given ipsw is not a directory
- char* s = tmpf + strlen(tmpf) - 1;
- char* p = s;
- while (*p != '\0' && *p != '.' && *p != '/' && *p != '\\') p--;
- if (s - p < 6) {
- if (*p == '.') {
- *p = '\0';
- }
- }
- }
-
- if (stat(tmpf, &st) < 0) {
- __mkdir(tmpf, 0755);
- }
- strcat(tmpf, "/");
- strcat(tmpf, fsname);
-
- memset(&st, '\0', sizeof(struct stat));
- if (stat(tmpf, &st) == 0) {
- uint64_t fssize = 0;
- ipsw_get_file_size(client->ipsw, fsname, &fssize);
- if ((fssize > 0) && ((uint64_t)st.st_size == fssize)) {
- info("Using cached filesystem from '%s'\n", tmpf);
- filesystem = strdup(tmpf);
- }
- }
-
- if (!filesystem && !(client->flags & FLAG_SHSHONLY)) {
- char extfn[1024];
- strcpy(extfn, tmpf);
- strcat(extfn, ".extract");
- char lockfn[1024];
- strcpy(lockfn, tmpf);
- strcat(lockfn, ".lock");
- lock_info_t li;
-
- lock_file(lockfn, &li);
- FILE* extf = NULL;
- if (access(extfn, F_OK) != 0) {
- extf = fopen(extfn, "wb");
- }
- unlock_file(&li);
- if (!extf) {
- // use temp filename
- filesystem = get_temp_filename("ipsw_");
- if (!filesystem) {
- error("WARNING: Could not get temporary filename, using '%s' in current directory\n", fsname);
- filesystem = strdup(fsname);
- }
- delete_fs = 1;
- } else {
- // use <fsname>.extract as filename
- filesystem = strdup(extfn);
- fclose(extf);
- }
- remove(lockfn);
-
- // Extract filesystem from IPSW
- info("Extracting filesystem from IPSW: %s\n", fsname);
- if (ipsw_extract_to_file_with_progress(client->ipsw, fsname, filesystem, 1) < 0) {
- error("ERROR: Unable to extract filesystem from IPSW\n");
- if (client->tss)
- plist_free(client->tss);
- info("Removing %s\n", filesystem);
- unlink(filesystem);
- return -1;
- }
-
- if (strstr(filesystem, ".extract")) {
- // rename <fsname>.extract to <fsname>
- remove(tmpf);
- rename(filesystem, tmpf);
- free(filesystem);
- filesystem = strdup(tmpf);
- }
- }
-
idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.2);
/* retrieve shsh blobs if required */
@@ -1140,8 +1038,6 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
}
if (client->flags & FLAG_QUIT) {
- if (delete_fs && filesystem)
- unlink(filesystem);
return -1;
}
if (client->flags & FLAG_SHSHONLY) {
@@ -1196,8 +1092,6 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
}
idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.25);
if (client->flags & FLAG_QUIT) {
- if (delete_fs && filesystem)
- unlink(filesystem);
return -1;
}
@@ -1214,8 +1108,6 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.3);
if (client->flags & FLAG_QUIT) {
- if (delete_fs && filesystem)
- unlink(filesystem);
return -1;
}
@@ -1226,16 +1118,12 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
if ((client->flags & FLAG_CUSTOM) && limera1n_is_supported(client->device)) {
info("connecting to DFU\n");
if (dfu_client_new(client) < 0) {
- if (delete_fs && filesystem)
- unlink(filesystem);
return -1;
}
info("exploiting with limera1n\n");
if (limera1n_exploit(client->device, &client->dfu->client) != 0) {
error("ERROR: limera1n exploit failed\n");
dfu_client_free(client);
- if (delete_fs && filesystem)
- unlink(filesystem);
return -1;
}
dfu_client_free(client);
@@ -1245,8 +1133,6 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
error("ERROR: Unable to place device into recovery mode from DFU mode\n");
if (client->tss)
plist_free(client->tss);
- if (delete_fs && filesystem)
- unlink(filesystem);
return -2;
}
} else if (client->mode == MODE_RECOVERY) {
@@ -1256,8 +1142,6 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
/* send ApTicket */
if (recovery_send_ticket(client) < 0) {
error("ERROR: Unable to send APTicket\n");
- if (delete_fs && filesystem)
- unlink(filesystem);
return -2;
}
}
@@ -1269,8 +1153,6 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
if (recovery_send_ibec(client, build_identity) < 0) {
mutex_unlock(&client->device_event_mutex);
error("ERROR: Unable to send iBEC\n");
- if (delete_fs && filesystem)
- unlink(filesystem);
return -2;
}
recovery_client_free(client);
@@ -1283,8 +1165,6 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
if (!(client->flags & FLAG_QUIT)) {
error("ERROR: Device did not disconnect. Possibly invalid iBEC. Reset device and try again.\n");
}
- if (delete_fs && filesystem)
- unlink(filesystem);
return -2;
}
debug("Waiting for device to reconnect in recovery mode...\n");
@@ -1294,16 +1174,12 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
if (!(client->flags & FLAG_QUIT)) {
error("ERROR: Device did not reconnect in recovery mode. Possibly invalid iBEC. Reset device and try again.\n");
}
- if (delete_fs && filesystem)
- unlink(filesystem);
return -2;
}
mutex_unlock(&client->device_event_mutex);
}
idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.5);
if (client->flags & FLAG_QUIT) {
- if (delete_fs && filesystem)
- unlink(filesystem);
return -1;
}
@@ -1315,8 +1191,6 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
if (get_ap_nonce(client, &nonce, &nonce_size) < 0) {
error("ERROR: Unable to get nonce from device!\n");
recovery_send_reset(client);
- if (delete_fs && filesystem)
- unlink(filesystem);
return -2;
}
@@ -1336,14 +1210,10 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
plist_free(client->tss);
if (get_tss_response(client, build_identity, &client->tss) < 0) {
error("ERROR: Unable to get SHSH blobs for this device\n");
- if (delete_fs && filesystem)
- unlink(filesystem);
return -1;
}
if (!client->tss) {
error("ERROR: can't continue without TSS\n");
- if (delete_fs && filesystem)
- unlink(filesystem);
return -1;
}
fixup_tss(client->tss);
@@ -1351,8 +1221,6 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
}
idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.7);
if (client->flags & FLAG_QUIT) {
- if (delete_fs && filesystem)
- unlink(filesystem);
return -1;
}
@@ -1362,8 +1230,6 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
error("ERROR: Unable to place device into restore mode\n");
if (client->tss)
plist_free(client->tss);
- if (delete_fs && filesystem)
- unlink(filesystem);
return -2;
}
recovery_client_free(client);
@@ -1378,8 +1244,6 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
mutex_unlock(&client->device_event_mutex);
error("ERROR: Device failed to enter restore mode.\n");
error("Please make sure that usbmuxd is running.\n");
- if (delete_fs && filesystem)
- unlink(filesystem);
return -1;
}
mutex_unlock(&client->device_event_mutex);
@@ -1393,19 +1257,13 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
}
client->ignore_device_add_events = 1;
info("About to restore device... \n");
- result = restore_device(client, build_identity, filesystem);
+ result = restore_device(client, build_identity);
if (result < 0) {
error("ERROR: Unable to restore device\n");
- if (delete_fs && filesystem)
- unlink(filesystem);
return result;
}
}
- info("Cleaning up...\n");
- if (delete_fs && filesystem)
- unlink(filesystem);
-
/* special handling of older AppleTVs as they enter Recovery mode on boot when plugged in to USB */
if ((strncmp(client->device->product_type, "AppleTV", 7) == 0) && (client->device->product_type[7] < '5')) {
if (recovery_client_new(client) == 0) {
@@ -1476,7 +1334,7 @@ void idevicerestore_client_free(struct idevicerestore_client_t* client)
free(client->srnm);
}
if (client->ipsw) {
- free(client->ipsw);
+ ipsw_close(client->ipsw);
}
if (client->version) {
free(client->version);
@@ -1535,11 +1393,11 @@ void idevicerestore_set_ipsw(struct idevicerestore_client_t* client, const char*
if (!client)
return;
if (client->ipsw) {
- free(client->ipsw);
+ ipsw_close(client->ipsw);
client->ipsw = NULL;
}
if (path) {
- client->ipsw = strdup(path);
+ client->ipsw = ipsw_open(path);
}
}
@@ -1795,7 +1653,12 @@ int main(int argc, char* argv[]) {
info("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
if (ipsw) {
- client->ipsw = strdup(ipsw);
+ // verify if ipsw file exists
+ client->ipsw = ipsw_open(ipsw);
+ if (!client->ipsw) {
+ error("ERROR: Firmware file %s cannot be opened.\n", ipsw);
+ return -1;
+ }
}
curl_global_init(CURL_GLOBAL_ALL);
@@ -2570,7 +2433,7 @@ int build_manifest_get_identity_count(plist_t build_manifest)
return plist_array_get_size(build_identities_array);
}
-int extract_component(const char* ipsw, const char* path, unsigned char** component_data, unsigned int* component_size)
+int extract_component(ipsw_archive_t ipsw, const char* path, unsigned char** component_data, unsigned int* component_size)
{
char* component_name = NULL;
if (!ipsw || !path || !component_data || !component_size) {
@@ -2585,7 +2448,7 @@ int extract_component(const char* ipsw, const char* path, unsigned char** compon
info("Extracting %s (%s)...\n", component_name, path);
if (ipsw_extract_to_memory(ipsw, path, component_data, component_size) < 0) {
- error("ERROR: Unable to extract %s from %s\n", component_name, ipsw);
+ error("ERROR: Unable to extract %s from %s\n", component_name, ipsw->path);
return -1;
}
@@ -2718,7 +2581,7 @@ void build_identity_print_information(plist_t build_identity)
node = NULL;
}
-int build_identity_check_components_in_ipsw(plist_t build_identity, const char *ipsw)
+int build_identity_check_components_in_ipsw(plist_t build_identity, ipsw_archive_t ipsw)
{
plist_t manifest_node = plist_dict_get_item(build_identity, "Manifest");
if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) {
diff --git a/src/idevicerestore.h b/src/idevicerestore.h
index 8a5736f..880562f 100644
--- a/src/idevicerestore.h
+++ b/src/idevicerestore.h
@@ -52,6 +52,8 @@ extern "C" {
#define RESTORE_VARIANT_MACOS_RECOVERY_OS "macOS Customer"
struct idevicerestore_client_t;
+struct ipsw_archive;
+typedef struct ipsw_archive* ipsw_archive_t;
enum {
RESTORE_STEP_DETECT = 0,
@@ -108,11 +110,10 @@ plist_t build_manifest_get_build_identity_for_model(plist_t build_manifest, cons
plist_t build_manifest_get_build_identity_for_model_with_variant(plist_t build_manifest, const char *hardware_model, const char *variant, int exact);
int build_manifest_get_build_count(plist_t build_manifest);
void build_identity_print_information(plist_t build_identity);
-int build_identity_check_components_in_ipsw(plist_t build_identity, const char* ipsw);
int build_identity_has_component(plist_t build_identity, const char* component);
int build_identity_get_component_path(plist_t build_identity, const char* component, char** path);
-int ipsw_extract_filesystem(const char* ipsw, plist_t build_identity, char** filesystem);
-int extract_component(const char* ipsw, const char* path, unsigned char** component_data, unsigned int* component_size);
+int ipsw_extract_filesystem(ipsw_archive_t ipsw, plist_t build_identity, char** filesystem);
+int extract_component(ipsw_archive_t ipsw, const char* path, unsigned char** component_data, unsigned int* component_size);
int personalize_component(const char *component, const unsigned char* component_data, unsigned int component_size, plist_t tss_response, unsigned char** personalized_component, unsigned int* personalized_component_size);
int get_preboard_manifest(struct idevicerestore_client_t* client, plist_t build_identity, plist_t* manifest);
diff --git a/src/ipsw.c b/src/ipsw.c
index fafe583..58d817c 100644
--- a/src/ipsw.c
+++ b/src/ipsw.c
@@ -55,16 +55,8 @@
#define BUFSIZE 0x100000
-typedef struct {
- struct zip* zip;
- char *path;
-} ipsw_archive;
-
static int cancel_flag = 0;
-ipsw_archive* ipsw_open(const char* ipsw);
-void ipsw_close(ipsw_archive* archive);
-
static char* build_path(const char* path, const char* file)
{
size_t plen = strlen(path);
@@ -118,11 +110,14 @@ int ipsw_print_info(const char* path)
uint32_t plist_len = 0;
if (memcmp(&magic, "PK\x03\x04", 4) == 0) {
+ ipsw_archive_t ipsw = ipsw_open(thepath);
unsigned int rlen = 0;
- if (ipsw_extract_to_memory(thepath, "BuildManifest.plist", (unsigned char**)&plist_buf, &rlen) < 0) {
+ if (ipsw_extract_to_memory(ipsw, "BuildManifest.plist", (unsigned char**)&plist_buf, &rlen) < 0) {
+ ipsw_close(ipsw);
error("ERROR: Failed to extract BuildManifest.plist from IPSW!\n");
return -1;
}
+ ipsw_close(ipsw);
plist_len = (uint32_t)rlen;
} else {
size_t rlen = 0;
@@ -310,10 +305,10 @@ int ipsw_print_info(const char* path)
return 0;
}
-ipsw_archive* ipsw_open(const char* ipsw)
+ipsw_archive_t ipsw_open(const char* ipsw)
{
int err = 0;
- ipsw_archive* archive = (ipsw_archive*) malloc(sizeof(ipsw_archive));
+ ipsw_archive_t archive = (ipsw_archive_t)malloc(sizeof(struct ipsw_archive));
if (archive == NULL) {
error("ERROR: Out of memory\n");
return NULL;
@@ -324,7 +319,6 @@ ipsw_archive* ipsw_open(const char* ipsw)
error("ERROR: ipsw_open %s: %s\n", ipsw, strerror(errno));
return NULL;
}
- archive->path = strdup(ipsw);
if (S_ISDIR(fst.st_mode)) {
archive->zip = NULL;
} else {
@@ -335,7 +329,20 @@ ipsw_archive* ipsw_open(const char* ipsw)
return NULL;
}
}
- return archive;
+ archive->path = strdup(ipsw);
+ return (ipsw_archive_t)archive;
+}
+
+void ipsw_close(ipsw_archive_t ipsw)
+{
+ if (ipsw != NULL) {
+ free(ipsw->path);
+ if (ipsw->zip) {
+ zip_unchange_all(ipsw->zip);
+ zip_close(ipsw->zip);
+ }
+ free(ipsw);
+ }
}
int ipsw_is_directory(const char* ipsw)
@@ -348,37 +355,33 @@ int ipsw_is_directory(const char* ipsw)
return S_ISDIR(fst.st_mode);
}
-int ipsw_get_file_size(const char* ipsw, const char* infile, uint64_t* size)
+int ipsw_get_file_size(ipsw_archive_t ipsw, const char* infile, uint64_t* size)
{
- ipsw_archive* archive = ipsw_open(ipsw);
- if (archive == NULL) {
+ if (ipsw == NULL) {
error("ERROR: Invalid archive\n");
return -1;
}
- if (archive->zip) {
- int zindex = zip_name_locate(archive->zip, infile, 0);
+ if (ipsw->zip) {
+ int zindex = zip_name_locate(ipsw->zip, infile, 0);
if (zindex < 0) {
error("ERROR: zip_name_locate: %s\n", infile);
- ipsw_close(archive);
return -1;
}
struct zip_stat zstat;
zip_stat_init(&zstat);
- if (zip_stat_index(archive->zip, zindex, 0, &zstat) != 0) {
+ if (zip_stat_index(ipsw->zip, zindex, 0, &zstat) != 0) {
error("ERROR: zip_stat_index: %s\n", infile);
- ipsw_close(archive);
return -1;
}
*size = zstat.size;
} else {
- char *filepath = build_path(archive->path, infile);
+ char *filepath = build_path(ipsw->path, infile);
struct stat fst;
if (stat(filepath, &fst) != 0) {
free(filepath);
- ipsw_close(archive);
return -1;
}
free(filepath);
@@ -386,30 +389,22 @@ int ipsw_get_file_size(const char* ipsw, const char* infile, uint64_t* size)
*size = fst.st_size;
}
- ipsw_close(archive);
return 0;
}
-int ipsw_extract_to_file_with_progress(const char* ipsw, const char* infile, const char* outfile, int print_progress)
+int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile, const char* outfile, int print_progress)
{
int ret = 0;
- ipsw_archive* archive = NULL;
if (!ipsw || !infile || !outfile) {
error("ERROR: Invalid argument\n");
return -1;
}
- archive = ipsw_open(ipsw);
- if (archive == NULL) {
- error("ERROR: Invalid archive\n");
- return -1;
- }
-
cancel_flag = 0;
- if (archive->zip) {
- int zindex = zip_name_locate(archive->zip, infile, 0);
+ if (ipsw->zip) {
+ int zindex = zip_name_locate(ipsw->zip, infile, 0);
if (zindex < 0) {
error("ERROR: zip_name_locate: %s\n", infile);
return -1;
@@ -417,7 +412,7 @@ int ipsw_extract_to_file_with_progress(const char* ipsw, const char* infile, con
struct zip_stat zstat;
zip_stat_init(&zstat);
- if (zip_stat_index(archive->zip, zindex, 0, &zstat) != 0) {
+ if (zip_stat_index(ipsw->zip, zindex, 0, &zstat) != 0) {
error("ERROR: zip_stat_index: %s\n", infile);
return -1;
}
@@ -428,7 +423,7 @@ int ipsw_extract_to_file_with_progress(const char* ipsw, const char* infile, con
return -1;
}
- struct zip_file* zfile = zip_fopen_index(archive->zip, zindex, 0);
+ struct zip_file* zfile = zip_fopen_index(ipsw->zip, zindex, 0);
if (zfile == NULL) {
error("ERROR: zip_fopen_index: %s\n", infile);
return -1;
@@ -472,7 +467,7 @@ int ipsw_extract_to_file_with_progress(const char* ipsw, const char* infile, con
fclose(fd);
zip_fclose(zfile);
} else {
- char *filepath = build_path(archive->path, infile);
+ char *filepath = build_path(ipsw->path, infile);
char actual_filepath[PATH_MAX+1];
char actual_outfile[PATH_MAX+1];
if (!filepath) {
@@ -553,76 +548,66 @@ int ipsw_extract_to_file_with_progress(const char* ipsw, const char* infile, con
leave:
free(filepath);
}
- ipsw_close(archive);
if (cancel_flag) {
ret = -2;
}
return ret;
}
-int ipsw_extract_to_file(const char* ipsw, const char* infile, const char* outfile)
+int ipsw_extract_to_file(ipsw_archive_t ipsw, const char* infile, const char* outfile)
{
return ipsw_extract_to_file_with_progress(ipsw, infile, outfile, 0);
}
-int ipsw_file_exists(const char* ipsw, const char* infile)
+int ipsw_file_exists(ipsw_archive_t ipsw, const char* infile)
{
- ipsw_archive* archive = ipsw_open(ipsw);
- if (archive == NULL) {
+ if (!ipsw) {
return 0;
}
- if (archive->zip) {
- int zindex = zip_name_locate(archive->zip, infile, 0);
+ if (ipsw->zip) {
+ int zindex = zip_name_locate(ipsw->zip, infile, 0);
if (zindex < 0) {
- ipsw_close(archive);
return 0;
}
} else {
- char *filepath = build_path(archive->path, infile);
+ char *filepath = build_path(ipsw->path, infile);
if (access(filepath, R_OK) != 0) {
free(filepath);
- ipsw_close(archive);
return 0;
}
free(filepath);
}
- ipsw_close(archive);
-
return 1;
}
-int ipsw_extract_to_memory(const char* ipsw, const char* infile, unsigned char** pbuffer, unsigned int* psize)
+int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned char** pbuffer, unsigned int* psize)
{
size_t size = 0;
unsigned char* buffer = NULL;
- ipsw_archive* archive = ipsw_open(ipsw);
- if (archive == NULL) {
+ if (ipsw == NULL) {
error("ERROR: Invalid archive\n");
return -1;
}
- if (archive->zip) {
- int zindex = zip_name_locate(archive->zip, infile, 0);
+ if (ipsw->zip) {
+ int zindex = zip_name_locate(ipsw->zip, infile, 0);
if (zindex < 0) {
debug("NOTE: zip_name_locate: '%s' not found in archive.\n", infile);
- ipsw_close(archive);
return -1;
}
struct zip_stat zstat;
zip_stat_init(&zstat);
- if (zip_stat_index(archive->zip, zindex, 0, &zstat) != 0) {
+ if (zip_stat_index(ipsw->zip, zindex, 0, &zstat) != 0) {
error("ERROR: zip_stat_index: %s\n", infile);
- ipsw_close(archive);
return -1;
}
- struct zip_file* zfile = zip_fopen_index(archive->zip, zindex, 0);
+ struct zip_file* zfile = zip_fopen_index(ipsw->zip, zindex, 0);
if (zfile == NULL) {
error("ERROR: zip_fopen_index: %s\n", infile);
- ipsw_close(archive);
return -1;
}
@@ -631,7 +616,6 @@ int ipsw_extract_to_memory(const char* ipsw, const char* infile, unsigned char**
if (buffer == NULL) {
error("ERROR: Out of memory\n");
zip_fclose(zfile);
- ipsw_close(archive);
return -1;
}
@@ -639,7 +623,6 @@ int ipsw_extract_to_memory(const char* ipsw, const char* infile, unsigned char**
error("ERROR: zip_fread: %s\n", infile);
zip_fclose(zfile);
free(buffer);
- ipsw_close(archive);
return -1;
}
@@ -647,7 +630,7 @@ int ipsw_extract_to_memory(const char* ipsw, const char* infile, unsigned char**
zip_fclose(zfile);
} else {
- char *filepath = build_path(archive->path, infile);
+ char *filepath = build_path(ipsw->path, infile);
struct stat fst;
#ifdef WIN32
if (stat(filepath, &fst) != 0) {
@@ -656,7 +639,6 @@ int ipsw_extract_to_memory(const char* ipsw, const char* infile, unsigned char**
#endif
error("ERROR: %s: stat failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
- ipsw_close(archive);
return -1;
}
size = fst.st_size;
@@ -664,7 +646,6 @@ int ipsw_extract_to_memory(const char* ipsw, const char* infile, unsigned char**
if (buffer == NULL) {
error("ERROR: Out of memory\n");
free(filepath);
- ipsw_close(archive);
return -1;
}
@@ -674,7 +655,6 @@ int ipsw_extract_to_memory(const char* ipsw, const char* infile, unsigned char**
error("ERROR: %s: readlink failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
free(buffer);
- ipsw_close(archive);
return -1;
}
} else {
@@ -684,7 +664,6 @@ int ipsw_extract_to_memory(const char* ipsw, const char* infile, unsigned char**
error("ERROR: %s: fopen failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
free(buffer);
- ipsw_close(archive);
return -2;
}
if (fread(buffer, 1, size, f) != size) {
@@ -692,7 +671,6 @@ int ipsw_extract_to_memory(const char* ipsw, const char* infile, unsigned char**
error("ERROR: %s: fread failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
free(buffer);
- ipsw_close(archive);
return -1;
}
fclose(f);
@@ -703,45 +681,40 @@ int ipsw_extract_to_memory(const char* ipsw, const char* infile, unsigned char**
free(filepath);
}
- ipsw_close(archive);
*pbuffer = buffer;
*psize = size;
return 0;
}
-int ipsw_extract_send(const char* ipsw, const char* infile, int blocksize, ipsw_send_cb send_callback, void* ctx)
+int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ipsw_send_cb send_callback, void* ctx)
{
unsigned char* buffer = NULL;
size_t done = 0;
size_t total_size = 0;
- ipsw_archive* archive = ipsw_open(ipsw);
- if (archive == NULL) {
+ if (ipsw == NULL) {
error("ERROR: Invalid archive\n");
return -1;
}
- if (archive->zip) {
- int zindex = zip_name_locate(archive->zip, infile, 0);
+ if (ipsw->zip) {
+ int zindex = zip_name_locate(ipsw->zip, infile, 0);
if (zindex < 0) {
debug("NOTE: zip_name_locate: '%s' not found in archive.\n", infile);
- ipsw_close(archive);
return -1;
}
struct zip_stat zstat;
zip_stat_init(&zstat);
- if (zip_stat_index(archive->zip, zindex, 0, &zstat) != 0) {
+ if (zip_stat_index(ipsw->zip, zindex, 0, &zstat) != 0) {
error("ERROR: zip_stat_index: %s\n", infile);
- ipsw_close(archive);
return -1;
}
- struct zip_file* zfile = zip_fopen_index(archive->zip, zindex, 0);
+ struct zip_file* zfile = zip_fopen_index(ipsw->zip, zindex, 0);
if (zfile == NULL) {
error("ERROR: zip_fopen_index: %s\n", infile);
- ipsw_close(archive);
return -1;
}
@@ -750,7 +723,6 @@ int ipsw_extract_send(const char* ipsw, const char* infile, int blocksize, ipsw_
if (buffer == NULL) {
error("ERROR: Out of memory\n");
zip_fclose(zfile);
- ipsw_close(archive);
return -1;
}
@@ -771,10 +743,9 @@ int ipsw_extract_send(const char* ipsw, const char* infile, int blocksize, ipsw_
}
done += zr;
}
- zip_fclose(zfile);
free(buffer);
} else {
- char *filepath = build_path(archive->path, infile);
+ char *filepath = build_path(ipsw->path, infile);
struct stat fst;
#ifdef WIN32
if (stat(filepath, &fst) != 0) {
@@ -783,7 +754,6 @@ int ipsw_extract_send(const char* ipsw, const char* infile, int blocksize, ipsw_
#endif
error("ERROR: %s: stat failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
- ipsw_close(archive);
return -1;
}
total_size = fst.st_size;
@@ -791,7 +761,6 @@ int ipsw_extract_send(const char* ipsw, const char* infile, int blocksize, ipsw_
if (buffer == NULL) {
error("ERROR: Out of memory\n");
free(filepath);
- ipsw_close(archive);
return -1;
}
@@ -802,7 +771,6 @@ int ipsw_extract_send(const char* ipsw, const char* infile, int blocksize, ipsw_
error("ERROR: %s: readlink failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
free(buffer);
- ipsw_close(archive);
return -1;
}
send_callback(ctx, buffer, (size_t)rl);
@@ -813,7 +781,6 @@ int ipsw_extract_send(const char* ipsw, const char* infile, int blocksize, ipsw_
error("ERROR: %s: fopen failed for %s: %s\n", __func__, filepath, strerror(errno));
free(filepath);
free(buffer);
- ipsw_close(archive);
return -2;
}
@@ -838,7 +805,6 @@ int ipsw_extract_send(const char* ipsw, const char* infile, int blocksize, ipsw_
free(filepath);
free(buffer);
}
- ipsw_close(archive);
if (done < total_size) {
error("ERROR: %s: Sending file data for %s failed (sent %" PRIu64 "/%" PRIu64 ")\n", __func__, infile, (uint64_t)done, (uint64_t)total_size);
@@ -851,7 +817,7 @@ int ipsw_extract_send(const char* ipsw, const char* infile, int blocksize, ipsw_
return 0;
}
-int ipsw_extract_build_manifest(const char* ipsw, plist_t* buildmanifest, int *tss_enabled)
+int ipsw_extract_build_manifest(ipsw_archive_t ipsw, plist_t* buildmanifest, int *tss_enabled)
{
unsigned int size = 0;
unsigned char* data = NULL;
@@ -881,7 +847,7 @@ int ipsw_extract_build_manifest(const char* ipsw, plist_t* buildmanifest, int *t
return -1;
}
-int ipsw_extract_restore_plist(const char* ipsw, plist_t* restore_plist)
+int ipsw_extract_restore_plist(ipsw_archive_t ipsw, plist_t* restore_plist)
{
unsigned int size = 0;
unsigned char* data = NULL;
@@ -895,10 +861,10 @@ int ipsw_extract_restore_plist(const char* ipsw, plist_t* restore_plist)
return -1;
}
-static int ipsw_list_contents_recurse(ipsw_archive *archive, const char *path, ipsw_list_cb cb, void *ctx)
+static int ipsw_list_contents_recurse(ipsw_archive_t ipsw, const char *path, ipsw_list_cb cb, void *ctx)
{
int ret = 0;
- char *base = build_path(archive->path, path);
+ char *base = build_path(ipsw->path, path);
DIR *dirp = opendir(base);
@@ -936,10 +902,10 @@ static int ipsw_list_contents_recurse(ipsw_archive *archive, const char *path, i
break;
}
- ret = cb(ctx, archive->path, subpath, &st);
+ ret = cb(ctx, ipsw, subpath, &st);
if (ret >= 0 && S_ISDIR(st.st_mode))
- ipsw_list_contents_recurse(archive, subpath, cb, ctx);
+ ipsw_list_contents_recurse(ipsw, subpath, cb, ctx);
free(fpath);
free(subpath);
@@ -950,21 +916,19 @@ static int ipsw_list_contents_recurse(ipsw_archive *archive, const char *path, i
return ret;
}
-int ipsw_list_contents(const char* ipsw, ipsw_list_cb cb, void *ctx)
+int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx)
{
int ret = 0;
- ipsw_archive* archive = ipsw_open(ipsw);
- if (archive == NULL) {
- error("ERROR: Invalid archive\n");
+ if (ipsw == NULL) {
+ error("ERROR: Invalid IPSW archive\n");
return -1;
}
- if (archive->zip) {
- int64_t entries = zip_get_num_entries(archive->zip, 0);
+ if (ipsw->zip) {
+ int64_t entries = zip_get_num_entries(ipsw->zip, 0);
if (entries < 0) {
error("ERROR: zip_get_num_entries failed\n");
- ipsw_close(archive);
return -1;
}
@@ -972,7 +936,7 @@ int ipsw_list_contents(const char* ipsw, ipsw_list_cb cb, void *ctx)
zip_stat_t stat;
zip_stat_init(&stat);
- if (zip_stat_index(archive->zip, index, 0, &stat) < 0) {
+ if (zip_stat_index(ipsw->zip, index, 0, &stat) < 0) {
error("ERROR: zip_stat_index failed for %s\n", stat.name);
ret = -1;
continue;
@@ -980,7 +944,7 @@ int ipsw_list_contents(const char* ipsw, ipsw_list_cb cb, void *ctx)
uint8_t opsys;
uint32_t attributes;
- if (zip_file_get_external_attributes(archive->zip, index, 0, &opsys, &attributes) < 0) {
+ if (zip_file_get_external_attributes(ipsw->zip, index, 0, &opsys, &attributes) < 0) {
error("ERROR: zip_file_get_external_attributes failed for %s\n", stat.name);
ret = -1;
continue;
@@ -1010,25 +974,12 @@ int ipsw_list_contents(const char* ipsw, ipsw_list_cb cb, void *ctx)
break;
}
} else {
- ret = ipsw_list_contents_recurse(archive, "", cb, ctx);
+ ret = ipsw_list_contents_recurse(ipsw, "", cb, ctx);
}
- ipsw_close(archive);
return ret;
}
-void ipsw_close(ipsw_archive* archive)
-{
- if (archive != NULL) {
- free(archive->path);
- if (archive->zip) {
- zip_unchange_all(archive->zip);
- zip_close(archive->zip);
- }
- free(archive);
- }
-}
-
int ipsw_get_signed_firmwares(const char* product, plist_t* firmwares)
{
char url[256];
@@ -1352,3 +1303,91 @@ void ipsw_cancel(void)
{
cancel_flag++;
}
+
+ipsw_file_handle_t ipsw_file_open(ipsw_archive_t ipsw, const char* path)
+{
+ ipsw_file_handle_t handle = (ipsw_file_handle_t)calloc(1, sizeof(struct ipsw_file_handle));
+ if (ipsw->zip) {
+ int zindex = zip_name_locate(ipsw->zip, path, 0);
+ if (zindex < 0) {
+ error("ERROR: zip_name_locate: %s not found\n", path);
+ free(handle);
+ return NULL;
+ }
+ handle->zfile = zip_fopen_index(ipsw->zip, zindex, 0);
+ if (handle->zfile == NULL) {
+ error("ERROR: zip_fopen_index: %s could not be opened\n", path);
+ free(handle);
+ return NULL;
+ }
+
+ } else {
+ char *filepath = build_path(ipsw->path, path);
+ handle->file = fopen(filepath, "rb");
+ free(filepath);
+ if (!handle->file) {
+ error("ERROR: fopen: %s could not be opened\n", path);
+ free(handle);
+ return NULL;
+ }
+ }
+ return handle;
+}
+
+void ipsw_file_close(ipsw_file_handle_t handle)
+{
+ if (handle && handle->zfile) {
+ zip_fclose(handle->zfile);
+ } else if (handle && handle->file) {
+ fclose(handle->file);
+ }
+ free(handle);
+}
+
+int64_t ipsw_file_read(ipsw_file_handle_t handle, void* buffer, size_t size)
+{
+ if (handle && handle->zfile) {
+ zip_int64_t zr = zip_fread(handle->zfile, buffer, size);
+ return (int64_t)zr;
+ } else if (handle && handle->file) {
+ return fread(buffer, 1, size, handle->file);
+ } else {
+ error("ERROR: %s: Invalid file handle\n", __func__);
+ return -1;
+ }
+}
+
+int ipsw_file_seek(ipsw_file_handle_t handle, int64_t offset, int whence)
+{
+ if (handle && handle->zfile) {
+ return zip_fseek(handle->zfile, offset, whence);
+ } else if (handle && handle->file) {
+#ifdef WIN32
+ if (whence == SEEK_SET) {
+ rewind(handle->file);
+ }
+ return (_lseeki64(fileno(handle->file), offset, whence) < 0) ? -1 : 0;
+#else
+ return fseeko(handle->file, offset, whence);
+#endif
+ } else {
+ error("ERROR: %s: Invalid file handle\n", __func__);
+ return -1;
+ }
+}
+
+int64_t ipsw_file_tell(ipsw_file_handle_t handle)
+{
+ if (handle && handle->zfile) {
+ return zip_ftell(handle->zfile);
+ } else if (handle && handle->file) {
+#ifdef WIN32
+ return _lseeki64(fileno(handle->file), 0, SEEK_CUR);
+#else
+ return ftello(handle->file);
+#endif
+ } else {
+ error("ERROR: %s: Invalid file handle\n", __func__);
+ return -1;
+ }
+}
diff --git a/src/ipsw.h b/src/ipsw.h
index 84ea7a9..96bcb62 100644
--- a/src/ipsw.h
+++ b/src/ipsw.h
@@ -32,21 +32,44 @@ extern "C" {
#include <plist/plist.h>
#include <sys/stat.h>
+struct ipsw_archive {
+ struct zip* zip;
+ char *path;
+};
+typedef struct ipsw_archive* ipsw_archive_t;
+
+ipsw_archive_t ipsw_open(const char* ipsw);
+void ipsw_close(ipsw_archive_t ipsw);
+
int ipsw_print_info(const char* ipsw);
-typedef int (*ipsw_list_cb)(void *ctx, const char* ipsw, const char *name, struct stat *stat);
+typedef int (*ipsw_list_cb)(void *ctx, ipsw_archive_t ipsw, const char *name, struct stat *stat);
typedef int (*ipsw_send_cb)(void *ctx, void *data, size_t size);
+struct ipsw_file_handle {
+ FILE* file;
+ struct zip_file* zfile;
+};
+typedef struct ipsw_file_handle* ipsw_file_handle_t;
+
+ipsw_file_handle_t ipsw_file_open(ipsw_archive_t, const char* path);
+void ipsw_file_close(ipsw_file_handle_t handle);
+
+int64_t ipsw_file_read(ipsw_file_handle_t handle, void* buffer, size_t size);
+int ipsw_file_seek(ipsw_file_handle_t handle, int64_t offset, int whence);
+int64_t ipsw_file_tell(ipsw_file_handle_t handle);
+
int ipsw_is_directory(const char* ipsw);
-int ipsw_file_exists(const char* ipsw, const char* infile);
-int ipsw_get_file_size(const char* ipsw, const char* infile, uint64_t* size);
-int ipsw_extract_to_file(const char* ipsw, const char* infile, const char* outfile);
-int ipsw_extract_to_file_with_progress(const char* ipsw, const char* infile, const char* outfile, int print_progress);
-int ipsw_extract_to_memory(const char* ipsw, const char* infile, unsigned char** pbuffer, unsigned int* psize);
-int ipsw_extract_send(const char* ipsw, const char* infile, int blocksize, ipsw_send_cb send_callback, void* ctx);
-int ipsw_extract_build_manifest(const char* ipsw, plist_t* buildmanifest, int *tss_enabled);
-int ipsw_extract_restore_plist(const char* ipsw, plist_t* restore_plist);
-int ipsw_list_contents(const char* ipsw, ipsw_list_cb cb, void *ctx);
+
+int ipsw_file_exists(ipsw_archive_t ipsw, const char* infile);
+int ipsw_get_file_size(ipsw_archive_t ipsw, const char* infile, uint64_t* size);
+int ipsw_extract_to_file(ipsw_archive_t ipsw, const char* infile, const char* outfile);
+int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile, const char* outfile, int print_progress);
+int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned char** pbuffer, unsigned int* psize);
+int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ipsw_send_cb send_callback, void* ctx);
+int ipsw_extract_build_manifest(ipsw_archive_t ipsw, plist_t* buildmanifest, int *tss_enabled);
+int ipsw_extract_restore_plist(ipsw_archive_t ipsw, plist_t* restore_plist);
+int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx);
int ipsw_get_signed_firmwares(const char* product, plist_t* firmwares);
int ipsw_download_fw(const char *fwurl, unsigned char* isha1, const char* todir, char** ipswfile);
diff --git a/src/restore.c b/src/restore.c
index a7072f0..c1dd92d 100644
--- a/src/restore.c
+++ b/src/restore.c
@@ -896,13 +896,26 @@ static void restore_asr_progress_cb(double progress, void* userdata)
}
}
-int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t device, const char* filesystem)
+int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t device, plist_t build_identity)
{
asr_client_t asr = NULL;
info("About to send filesystem...\n");
+ ipsw_file_handle_t file = NULL;
+ char* fsname = NULL;
+ if (build_identity_get_component_path(build_identity, "OS", &fsname) < 0) {
+ error("ERROR: Unable to get path for filesystem component\n");
+ return -1;
+ }
+ file = ipsw_file_open(client->ipsw, fsname);
+ if (!file) {
+ error("ERROR: Unable to open '%s' in ipsw\n", fsname);
+ free(fsname);
+ }
+
if (asr_open_with_timeout(device, &asr) < 0) {
+ ipsw_file_close(file);
error("ERROR: Unable to connect to ASR\n");
return -1;
}
@@ -913,7 +926,8 @@ int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t de
// this step sends requested chunks of data from various offsets to asr so
// it can validate the filesystem before installing it
info("Validating the filesystem\n");
- if (asr_perform_validation(asr, filesystem) < 0) {
+ if (asr_perform_validation(asr, file) < 0) {
+ ipsw_file_close(file);
error("ERROR: ASR was unable to validate the filesystem\n");
asr_free(asr);
return -1;
@@ -923,11 +937,14 @@ int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t de
// once the target filesystem has been validated, ASR then requests the
// entire filesystem to be sent.
info("Sending filesystem now...\n");
- if (asr_send_payload(asr, filesystem) < 0) {
+ if (asr_send_payload(asr, file) < 0) {
+ ipsw_file_close(file);
error("ERROR: Unable to send payload to ASR\n");
asr_free(asr);
return -1;
}
+ ipsw_file_close(file);
+
info("Done sending filesystem\n");
asr_free(asr);
@@ -3275,7 +3292,7 @@ static int cpio_send_file(idevice_connection_t connection, const char *name, str
return 0;
}
-static int restore_bootability_send_one(void *ctx, const char *ipsw, const char *name, struct stat *stat)
+static int restore_bootability_send_one(void *ctx, ipsw_archive_t ipsw, const char *name, struct stat *stat)
{
idevice_connection_t connection = (idevice_connection_t)ctx;
const char *prefix = "BootabilityBundle/Restore/Bootability/";
@@ -3747,7 +3764,7 @@ int restore_send_buildidentity(restored_client_t restore, struct idevicerestore_
return 0;
}
-int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idevice_t device, restored_client_t restore, plist_t message, plist_t build_identity, const char* filesystem)
+int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idevice_t device, restored_client_t restore, plist_t message, plist_t build_identity)
{
plist_t node = NULL;
@@ -3759,7 +3776,7 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev
// this request is sent when restored is ready to receive the filesystem
if (!strcmp(type, "SystemImageData")) {
- if(restore_send_filesystem(client, device, filesystem) < 0) {
+ if(restore_send_filesystem(client, device, build_identity) < 0) {
error("ERROR: Unable to send filesystem\n");
return -2;
}
@@ -3795,7 +3812,7 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev
// this request is sent when restored is ready to receive the filesystem
else if (!strcmp(type, "RecoveryOSASRImage")) {
- if(restore_send_filesystem(client, device, filesystem) < 0) {
+ if(restore_send_filesystem(client, device, build_identity) < 0) {
error("ERROR: Unable to send filesystem\n");
return -2;
}
@@ -4038,7 +4055,7 @@ static void rp_status_cb(reverse_proxy_client_t client, reverse_proxy_status_t s
}
#endif
-int restore_device(struct idevicerestore_client_t* client, plist_t build_identity, const char* filesystem)
+int restore_device(struct idevicerestore_client_t* client, plist_t build_identity)
{
int err = 0;
char* type = NULL;
@@ -4361,7 +4378,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit
// files sent to the server by the client. these data requests include
// SystemImageData, RootTicket, KernelCache, NORData and BasebandData requests
if (!strcmp(type, "DataRequestMsg")) {
- err = restore_handle_data_request_msg(client, device, restore, message, build_identity, filesystem);
+ err = restore_handle_data_request_msg(client, device, restore, message, build_identity);
}
// restore logs are available if a previous restore failed
diff --git a/src/restore.h b/src/restore.h
index ad3b721..765f374 100644
--- a/src/restore.h
+++ b/src/restore.h
@@ -38,7 +38,6 @@ struct restore_client_t {
idevice_t device;
char* udid;
unsigned int operation;
- const char* filesystem;
uint64_t protocol_version;
restored_client_t client;
};
@@ -52,13 +51,13 @@ int restore_reboot(struct idevicerestore_client_t* client);
const char* restore_progress_string(unsigned int operation);
int restore_handle_status_msg(restored_client_t client, plist_t msg);
int restore_handle_progress_msg(struct idevicerestore_client_t* client, plist_t msg);
-int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idevice_t device, restored_client_t restore, plist_t message, plist_t build_identity, const char* filesystem);
+int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idevice_t device, restored_client_t restore, plist_t message, plist_t build_identity);
int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message);
int restore_send_root_ticket(restored_client_t restore, struct idevicerestore_client_t* client);
int restore_send_component(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, const char* component, const char* component_name);
-int restore_device(struct idevicerestore_client_t* client, plist_t build_identity, const char* filesystem);
+int restore_device(struct idevicerestore_client_t* client, plist_t build_identity);
int restore_open_with_timeout(struct idevicerestore_client_t* client);
-int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t device, const char* filesystem);
+int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t device, plist_t build_identity);
int restore_send_fdr_trust_data(restored_client_t restore, idevice_t device);
#ifdef __cplusplus