diff options
Diffstat (limited to 'src/ipsw.c')
| -rw-r--r-- | src/ipsw.c | 117 | 
1 files changed, 117 insertions, 0 deletions
| diff --git a/src/ipsw.c b/src/ipsw.c new file mode 100644 index 0000000..d33d95f --- /dev/null +++ b/src/ipsw.c @@ -0,0 +1,117 @@ +/* + * ipsw.h + * Utilities for extracting and manipulating IPSWs + * + * Copyright (c) 2010 Joshua Hill. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + */ + +#include <zip.h> +#include <stdlib.h> +#include <string.h> +#include "ipsw.h" + +ipsw_archive* ipsw_open(const char* ipsw) { +	int err = 0; +	ipsw_archive* archive = (ipsw_archive*) malloc(sizeof(ipsw_archive)); +	if(archive == NULL) { +		error("ERROR: Out of memory\n"); +		return NULL; +	} + +	archive->zip = zip_open(ipsw, 0, &err); +	if(archive->zip == NULL) { +		error("ERROR: zip_open: %s: %d\n", ipsw, err); +		free(archive); +		return NULL; +	} + +	return archive; +} + +ipsw_file* ipsw_extract_file(ipsw_archive* archive, const char* filename) { +	if(archive == NULL || archive->zip == NULL) { +		error("ERROR: Invalid archive\n"); +		return NULL; +	} + +	int zindex = zip_name_locate(archive->zip, filename, 0); +	if(zindex < 0) { +		error("ERROR: zip_name_locate: %s\n", filename); +		return NULL; +	} + +	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; +	} + +	struct zip_file* zfile = zip_fopen_index(archive->zip, zindex, 0); +	if(zfile == NULL) { +		error("ERROR: zip_fopen_index: %s\n", filename); +		return NULL; +	} + +	ipsw_file* file = (ipsw_file*) malloc(sizeof(ipsw_file)); +	if(file == NULL) { +		error("ERROR: Out of memory\n"); +		zip_fclose(zfile); +		return NULL; +	} + +	file->size = zstat.size; +	file->index = zstat.index; +	file->name = strdup(zstat.name); +	file->data = (unsigned char*) malloc(file->size); +	if(file->data == NULL) { +		error("ERROR: Out of memory\n"); +		ipsw_free_file(file); +		zip_fclose(zfile); +		return NULL; +	} + +	if(zip_fread(zfile, file->data, file->size) != file->size) { +		error("ERROR: zip_fread: %s\n", filename); +		ipsw_free_file(file); +		zip_fclose(zfile); +		return NULL; +	} + +	zip_fclose(zfile); +	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); +	} +} + +void ipsw_close(ipsw_archive* archive) { +	if(archive != NULL) { +		zip_unchange_all(archive->zip); +		zip_close(archive->zip); +		free(archive); +	} +} | 
