diff options
Diffstat (limited to 'src/ipsw.c')
-rw-r--r-- | src/ipsw.c | 133 |
1 files changed, 90 insertions, 43 deletions
@@ -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); |