From c5aef53c60055d9a18349e6fa8b8f135fb89f046 Mon Sep 17 00:00:00 2001
From: BALATON Zoltan
Date: Fri, 17 Oct 2014 00:25:26 +0200
Subject: Fix handling of files larger than 2GB on 32bit systems

---
 src/asr.c      | 33 +++++++++++++++++----------------
 src/download.c |  4 ----
 src/ipsw.c     | 26 +++++++++++++-------------
 3 files changed, 30 insertions(+), 33 deletions(-)

(limited to 'src')

diff --git a/src/asr.c b/src/asr.c
index 591b908..c82d48c 100644
--- a/src/asr.c
+++ b/src/asr.c
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <errno.h>
 #include <libimobiledevice/libimobiledevice.h>
 #include <openssl/sha.h>
 
@@ -207,9 +208,9 @@ int asr_perform_validation(asr_client_t asr, const char* filesystem) {
 		return -1;
 	}
 
-	fseek(file, 0, SEEK_END);
-	length = ftell(file);
-	fseek(file, 0, SEEK_SET);
+	fseeko(file, 0, SEEK_END);
+	length = ftello(file);
+	fseeko(file, 0, SEEK_SET);
 
 	payload_info = plist_new_dict();
 	plist_dict_set_item(payload_info, "Port", plist_new_uint(1));
@@ -258,8 +259,10 @@ int asr_perform_validation(asr_client_t asr, const char* filesystem) {
 		plist_get_string_val(node, &command);
 
 		if (!strcmp(command, "OOBData")) {
-			asr_handle_oob_data_request(asr, packet, file);
+			int ret = asr_handle_oob_data_request(asr, packet, file);
 			plist_free(packet);
+			if (ret < 0)
+				return ret;
 		} else if(!strcmp(command, "Payload")) {
 			plist_free(packet);
 			break;
@@ -298,21 +301,19 @@ int asr_handle_oob_data_request(asr_client_t asr, plist_t packet, FILE* file) {
 	oob_data = (char*) malloc(oob_length);
 	if (oob_data == NULL) {
 		error("ERROR: Out of memory\n");
-		plist_free(packet);
 		return -1;
 	}
 
-	fseek(file, oob_offset, SEEK_SET);
+	fseeko(file, oob_offset, SEEK_SET);
 	if (fread(oob_data, 1, oob_length, file) != oob_length) {
-		error("ERROR: Unable to read OOB data from filesystem offset\n");
-		plist_free(packet);
+		error("ERROR: Unable to read OOB data from filesystem offset: %s\n",
+		      strerror(errno));
 		free(oob_data);
 		return -1;
 	}
 
 	if (asr_send_buffer(asr, oob_data, oob_length) < 0) {
 		error("ERROR: Unable to send OOB data to ASR\n");
-		plist_free(packet);
 		free(oob_data);
 		return -1;
 	}
@@ -321,21 +322,21 @@ int asr_handle_oob_data_request(asr_client_t asr, plist_t packet, FILE* file) {
 }
 
 int asr_send_payload(asr_client_t asr, const char* filesystem) {
-	int i = 0;
 	char data[ASR_PAYLOAD_PACKET_SIZE];
 	FILE* file = NULL;
-	uint32_t bytes = 0;
-	uint32_t length = 0;
+	off_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;
 	}
 
-	fseek(file, 0, SEEK_END);
-	length = ftell(file);
-	fseek(file, 0, SEEK_SET);
+	fseeko(file, 0, SEEK_END);
+	length = ftello(file);
+	fseeko(file, 0, SEEK_SET);
 
 	int chunk = 0;
 	int add_checksum = 0;
@@ -399,7 +400,7 @@ int asr_send_payload(asr_client_t asr, const char* filesystem) {
 		}
 
 		bytes += size;
-		progress = ((double) bytes/ (double) length);
+		progress = ((double)bytes / (double)length);
 		if (asr->progress_cb && ((int)(progress*100) > asr->lastprogress)) {
 			asr->progress_cb(progress, asr->progress_cb_data);
 			asr->lastprogress = (int)(progress*100);
diff --git a/src/download.c b/src/download.c
index 6adc523..82087df 100644
--- a/src/download.c
+++ b/src/download.c
@@ -27,10 +27,6 @@
 #include "download.h"
 #include "common.h"
 
-#ifdef WIN32
-#define ftello(x) ftell(x)
-#endif
-
 typedef struct {
 	int length;
 	char* content;
diff --git a/src/ipsw.c b/src/ipsw.c
index 9f24784..061d00d 100644
--- a/src/ipsw.c
+++ b/src/ipsw.c
@@ -87,6 +87,7 @@ int ipsw_get_file_size(const char* ipsw, const char* infile, off_t* size) {
 }
 
 int ipsw_extract_to_file(const char* ipsw, const char* infile, const char* outfile) {
+	int ret = 0;
 	ipsw_archive* archive = ipsw_open(ipsw);
 	if (archive == NULL || archive->zip == NULL) {
 		error("ERROR: Invalid archive\n");
@@ -125,27 +126,26 @@ int ipsw_extract_to_file(const char* ipsw, const char* infile, const char* outfi
 		return -1;
 	}
 
-	int i = 0;
-	int size = 0;
-	int bytes = 0;
-	int count = 0;
-	double progress = 0;
+	off_t i, bytes = 0;
+	int count, size = BUFSIZE;
+	double progress;
 	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;
+			ret = -1;
+			break;
+		}
+		if (fwrite(buffer, 1, count, fd) != count) {
+			error("ERROR: frite: %s\n", outfile);
+			ret = -1;
+			break;
 		}
-		fwrite(buffer, 1, count, fd);
 
 		bytes += size;
-		progress = ((double) bytes/ (double) zstat.size) * 100.0;
+		progress = ((double)bytes / (double)zstat.size) * 100.0;
 		print_progress_bar(progress);
 	}
 
@@ -153,7 +153,7 @@ int ipsw_extract_to_file(const char* ipsw, const char* infile, const char* outfi
 	zip_fclose(zfile);
 	ipsw_close(archive);
 	free(buffer);
-	return 0;
+	return ret;
 }
 
 int ipsw_file_exists(const char* ipsw, const char* infile)
-- 
cgit v1.1-32-gdbae