mirror of
https://github.com/libimobiledevice/idevicerestore.git
synced 2026-03-18 19:52:26 +00:00
Refactor logging and add logfile support
idevicerestore will now also create a logfile automatically, unless disabled with --logfile=NONE.
This commit is contained in:
@@ -58,6 +58,10 @@ Prints usage information.
|
||||
.B \-C, \-\-cache\-path DIR
|
||||
Use specified directory for caching extracted or other reused files.
|
||||
.TP
|
||||
.B \-\-logfile PATH
|
||||
Write logging output to file at PATH. If PATH equals \f[B]NULL\f[] or \f[B]NONE\f[],
|
||||
no log file will be written. This disables automatic log file creation.
|
||||
.TP
|
||||
.B \-d, \-\-debug
|
||||
Enable communication debugging.
|
||||
.TP
|
||||
|
||||
@@ -29,6 +29,7 @@ bin_PROGRAMS = idevicerestore
|
||||
|
||||
idevicerestore_SOURCES = \
|
||||
idevicerestore.c idevicerestore.h \
|
||||
log.c log.h \
|
||||
endianness.h \
|
||||
common.c common.h \
|
||||
fls.c fls.h \
|
||||
|
||||
+4
-4
@@ -167,7 +167,7 @@ int ace3_create_binary(const unsigned char* uarp_fw, size_t uarp_size, uint64_t
|
||||
uint64_t boardid = 0;
|
||||
plist_get_uint_val(p_boardid, &boardid);
|
||||
if (boardid == bdid) {
|
||||
debug("DEBUG: %s: Found Board ID 0x%" PRIx64 "\n", __func__, bdid);
|
||||
logger(LL_DEBUG, "%s: Found Board ID 0x%" PRIx64 "\n", __func__, bdid);
|
||||
plist_t p4cc = plist_dict_get_item(payload, "Payload 4CC");
|
||||
plist_get_string_val(p4cc, &payload_4cc);
|
||||
plist_t matching = plist_dict_get_item(meta, "Personalization Matching Data");
|
||||
@@ -189,7 +189,7 @@ int ace3_create_binary(const unsigned char* uarp_fw, size_t uarp_size, uint64_t
|
||||
if (prev >= minrev && prev <= maxrev) {
|
||||
plist_t tags = plist_dict_get_item(match, "Personalization Matching Data Payload Tags");
|
||||
plist_get_string_val(tags, &data_payload_4ccs);
|
||||
debug("DEBUG: %s: Found matching tags %s\n", __func__, data_payload_4ccs);
|
||||
logger(LL_DEBUG, "%s: Found matching tags %s\n", __func__, data_payload_4ccs);
|
||||
break;
|
||||
}
|
||||
} while (match);
|
||||
@@ -201,11 +201,11 @@ int ace3_create_binary(const unsigned char* uarp_fw, size_t uarp_size, uint64_t
|
||||
plist_mem_free(iter);
|
||||
}
|
||||
if (!payload_4cc) {
|
||||
printf("Failed to get payload 4cc\n");
|
||||
logger(LL_ERROR, "Failed to get payload 4cc\n");
|
||||
return -1;
|
||||
}
|
||||
if (!data_payload_4ccs) {
|
||||
printf("Failed to get data payload 4ccs\n");
|
||||
logger(LL_ERROR, "Failed to get data payload 4ccs\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ int asr_open_with_timeout(idevice_t device, asr_client_t* asr, uint16_t port)
|
||||
if (port == 0) {
|
||||
port = ASR_DEFAULT_PORT;
|
||||
}
|
||||
debug("Connecting to ASR on port %u\n", port);
|
||||
logger(LL_VERBOSE, "Connecting to ASR on port %u\n", port);
|
||||
|
||||
for (i = 1; i <= attempts; i++) {
|
||||
device_error = idevice_connect(device, port, &connection);
|
||||
@@ -72,12 +72,12 @@ int asr_open_with_timeout(idevice_t device, asr_client_t* asr, uint16_t port)
|
||||
}
|
||||
|
||||
if (i >= attempts) {
|
||||
error("ERROR: Unable to connect to ASR client\n");
|
||||
logger(LL_ERROR, "Unable to connect to ASR client\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sleep(2);
|
||||
debug("Retrying connection...\n");
|
||||
logger(LL_VERBOSE, "Retrying connection...\n");
|
||||
}
|
||||
|
||||
asr_client_t asr_loc = (asr_client_t)malloc(sizeof(struct asr_client));
|
||||
@@ -88,7 +88,7 @@ int asr_open_with_timeout(idevice_t device, asr_client_t* asr, uint16_t port)
|
||||
plist_t data = NULL;
|
||||
asr_loc->checksum_chunks = 0;
|
||||
if (asr_receive(asr_loc, &data) < 0) {
|
||||
error("ERROR: Unable to receive data from ASR\n");
|
||||
logger(LL_ERROR, "Unable to receive data from ASR\n");
|
||||
asr_free(asr_loc);
|
||||
plist_free(data);
|
||||
return -1;
|
||||
@@ -99,8 +99,8 @@ int asr_open_with_timeout(idevice_t device, asr_client_t* asr, uint16_t port)
|
||||
char* strval = NULL;
|
||||
plist_get_string_val(node, &strval);
|
||||
if (strval && (strcmp(strval, "Initiate") != 0)) {
|
||||
error("ERROR: unexpected ASR plist received:\n");
|
||||
debug_plist(data);
|
||||
logger(LL_ERROR, "Unexpected ASR plist received\n");
|
||||
logger_dump_plist(LL_VERBOSE, data, 1);
|
||||
plist_free(data);
|
||||
asr_free(asr_loc);
|
||||
return -1;
|
||||
@@ -138,13 +138,13 @@ int asr_receive(asr_client_t asr, plist_t* data)
|
||||
|
||||
buffer = (char*)malloc(ASR_BUFFER_SIZE);
|
||||
if (buffer == NULL) {
|
||||
error("ERROR: Unable to allocate memory for ASR receive buffer\n");
|
||||
logger(LL_ERROR, "Unable to allocate memory for ASR receive buffer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
device_error = idevice_connection_receive(asr->connection, buffer, ASR_BUFFER_SIZE, &size);
|
||||
if (device_error != IDEVICE_E_SUCCESS) {
|
||||
error("ERROR: Unable to receive data from ASR\n");
|
||||
logger(LL_ERROR, "Unable to receive data from ASR\n");
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
@@ -152,9 +152,8 @@ int asr_receive(asr_client_t asr, plist_t* data)
|
||||
|
||||
*data = request;
|
||||
|
||||
debug("Received %d bytes:\n", size);
|
||||
if (idevicerestore_debug)
|
||||
debug_plist(request);
|
||||
logger(LL_DEBUG, "Received %d bytes:\n", size);
|
||||
logger_dump_plist(LL_DEBUG, request, 1);
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
@@ -166,7 +165,7 @@ int asr_send(asr_client_t asr, plist_t data)
|
||||
|
||||
plist_to_xml(data, &buffer, &size);
|
||||
if (asr_send_buffer(asr, buffer, size) < 0) {
|
||||
error("ERROR: Unable to send plist to ASR\n");
|
||||
logger(LL_ERROR, "Unable to send plist to ASR\n");
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
@@ -183,7 +182,7 @@ int asr_send_buffer(asr_client_t asr, const char* data, uint32_t size)
|
||||
|
||||
device_error = idevice_connection_send(asr->connection, data, size, &bytes);
|
||||
if (device_error != IDEVICE_E_SUCCESS || bytes != size) {
|
||||
error("ERROR: Unable to send data to ASR. Sent %u of %u bytes.\n", bytes, size);
|
||||
logger(LL_ERROR, "Unable to send data to ASR. Sent %u of %u bytes.\n", bytes, size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -240,19 +239,19 @@ int asr_perform_validation(asr_client_t asr, ipsw_file_handle_t file)
|
||||
|
||||
// Expected by device after every initiate
|
||||
if (asr_send_validation_packet_info(asr, length) < 0) {
|
||||
error("ERROR: Unable to send validation packet info to ASR\n");
|
||||
logger(LL_ERROR, "Unable to send validation packet info to ASR\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (asr_receive(asr, &packet) < 0) {
|
||||
error("ERROR: Unable to receive validation packet\n");
|
||||
logger(LL_ERROR, "Unable to receive validation packet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (packet == NULL) {
|
||||
if (attempts < 5) {
|
||||
info("Retrying to receive validation packet... %d\n", attempts);
|
||||
logger(LL_INFO, "Retrying to receive validation packet... %d\n", attempts);
|
||||
attempts++;
|
||||
sleep(1);
|
||||
continue;
|
||||
@@ -263,7 +262,7 @@ int asr_perform_validation(asr_client_t asr, ipsw_file_handle_t file)
|
||||
|
||||
node = plist_dict_get_item(packet, "Command");
|
||||
if (!node || plist_get_node_type(node) != PLIST_STRING) {
|
||||
error("ERROR: Unable to find command node in validation request\n");
|
||||
logger(LL_ERROR, "Unable to find command node in validation request\n");
|
||||
return -1;
|
||||
}
|
||||
plist_get_string_val(node, &command);
|
||||
@@ -279,7 +278,7 @@ int asr_perform_validation(asr_client_t asr, ipsw_file_handle_t file)
|
||||
|
||||
// Expected by device after every Initiate
|
||||
if (asr_send_validation_packet_info(asr, length) < 0) {
|
||||
error("ERROR: Unable to send validation packet info to ASR\n");
|
||||
logger(LL_ERROR, "Unable to send validation packet info to ASR\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -297,7 +296,7 @@ int asr_perform_validation(asr_client_t asr, ipsw_file_handle_t file)
|
||||
break;
|
||||
|
||||
} else {
|
||||
error("ERROR: Unknown command received from ASR\n");
|
||||
logger(LL_ERROR, "Unknown command received from ASR\n");
|
||||
plist_free(packet);
|
||||
return -1;
|
||||
}
|
||||
@@ -316,38 +315,38 @@ int asr_handle_oob_data_request(asr_client_t asr, plist_t packet, ipsw_file_hand
|
||||
|
||||
oob_length_node = plist_dict_get_item(packet, "OOB Length");
|
||||
if (!oob_length_node || PLIST_UINT != plist_get_node_type(oob_length_node)) {
|
||||
error("ERROR: Unable to find OOB data length\n");
|
||||
logger(LL_ERROR, "Unable to find OOB data length\n");
|
||||
return -1;
|
||||
}
|
||||
plist_get_uint_val(oob_length_node, &oob_length);
|
||||
|
||||
oob_offset_node = plist_dict_get_item(packet, "OOB Offset");
|
||||
if (!oob_offset_node || PLIST_UINT != plist_get_node_type(oob_offset_node)) {
|
||||
error("ERROR: Unable to find OOB data offset\n");
|
||||
logger(LL_ERROR, "Unable to find OOB data offset\n");
|
||||
return -1;
|
||||
}
|
||||
plist_get_uint_val(oob_offset_node, &oob_offset);
|
||||
|
||||
oob_data = (char*) malloc(oob_length);
|
||||
if (oob_data == NULL) {
|
||||
error("ERROR: Out of memory\n");
|
||||
logger(LL_ERROR, "Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ipsw_file_seek(file, oob_offset, SEEK_SET) < 0) {
|
||||
error("ERROR: Unable to seek to OOB offset 0x%" PRIx64 "\n", oob_offset);
|
||||
logger(LL_ERROR, "Unable to seek to OOB offset 0x%" PRIx64 "\n", oob_offset);
|
||||
free(oob_data);
|
||||
return -1;
|
||||
}
|
||||
int64_t ir = ipsw_file_read(file, oob_data, oob_length);
|
||||
if (ir != oob_length) {
|
||||
error("ERROR: Unable to read OOB data from filesystem offset 0x%" PRIx64 ", oob_length %" PRIu64 ", read returned %" PRIi64"\n", oob_offset, oob_length, ir);
|
||||
logger(LL_ERROR, "Unable to read OOB data from filesystem offset 0x%" PRIx64 ", oob_length %" PRIu64 ", read returned %" PRIi64"\n", oob_offset, oob_length, ir);
|
||||
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");
|
||||
logger(LL_ERROR, "Unable to send OOB data to ASR\n");
|
||||
free(oob_data);
|
||||
return -1;
|
||||
}
|
||||
@@ -377,7 +376,7 @@ int asr_send_payload(asr_client_t asr, ipsw_file_handle_t file)
|
||||
}
|
||||
|
||||
if (ipsw_file_read(file, data, size) != (int64_t)size) {
|
||||
error("Error reading filesystem\n");
|
||||
logger(LL_ERROR, "Error reading filesystem\n");
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
@@ -388,7 +387,7 @@ int asr_send_payload(asr_client_t asr, ipsw_file_handle_t file)
|
||||
sendsize += 20;
|
||||
}
|
||||
if (asr_send_buffer(asr, data, sendsize) < 0) {
|
||||
error("Unable to send filesystem payload chunk, retrying...\n");
|
||||
logger(LL_ERROR, "Unable to send filesystem payload chunk, retrying...\n");
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
|
||||
+319
-142
@@ -36,6 +36,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <libimobiledevice-glue/thread.h>
|
||||
#include <libimobiledevice-glue/collection.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
@@ -57,6 +58,13 @@
|
||||
|
||||
#define MAX_PRINT_LEN 64*1024
|
||||
|
||||
int global_quit_flag = 0;
|
||||
static const char* STARS = "******************************************************************************";
|
||||
static const char* SPACES = " ";
|
||||
static const char* POUNDS = "##############################################################################";
|
||||
|
||||
static uint32_t progress_unique_tag = 1;
|
||||
|
||||
struct idevicerestore_mode_t idevicerestore_modes[] = {
|
||||
{ 0, "Unknown" },
|
||||
{ 1, "WTF" },
|
||||
@@ -69,122 +77,17 @@ struct idevicerestore_mode_t idevicerestore_modes[] = {
|
||||
|
||||
int idevicerestore_debug = 0;
|
||||
|
||||
#define idevicerestore_err_buff_size 256
|
||||
static char idevicerestore_err_buff[idevicerestore_err_buff_size] = {0, };
|
||||
|
||||
static FILE* info_stream = NULL;
|
||||
static FILE* error_stream = NULL;
|
||||
static FILE* debug_stream = NULL;
|
||||
|
||||
static int info_disabled = 0;
|
||||
static int error_disabled = 0;
|
||||
static int debug_disabled = 0;
|
||||
|
||||
static mutex_t log_mutex;
|
||||
static thread_once_t init_once = THREAD_ONCE_INIT;
|
||||
|
||||
static void _log_init(void)
|
||||
{
|
||||
mutex_init(&log_mutex);
|
||||
}
|
||||
|
||||
void info(const char* format, ...)
|
||||
{
|
||||
if (info_disabled) return;
|
||||
thread_once(&init_once, _log_init);
|
||||
mutex_lock(&log_mutex);
|
||||
va_list vargs;
|
||||
va_start(vargs, format);
|
||||
vfprintf((info_stream) ? info_stream : stdout, format, vargs);
|
||||
va_end(vargs);
|
||||
fflush(info_stream?info_stream:stdout);
|
||||
mutex_unlock(&log_mutex);
|
||||
}
|
||||
|
||||
void error(const char* format, ...)
|
||||
{
|
||||
thread_once(&init_once, _log_init);
|
||||
mutex_lock(&log_mutex);
|
||||
va_list vargs, vargs2;
|
||||
va_start(vargs, format);
|
||||
va_copy(vargs2, vargs);
|
||||
vsnprintf(idevicerestore_err_buff, idevicerestore_err_buff_size, format, vargs);
|
||||
va_end(vargs);
|
||||
if (!error_disabled) {
|
||||
vfprintf((error_stream) ? error_stream : stderr, format, vargs2);
|
||||
}
|
||||
va_end(vargs2);
|
||||
fflush(error_stream?error_stream:stderr);
|
||||
mutex_unlock(&log_mutex);
|
||||
}
|
||||
|
||||
void debug(const char* format, ...)
|
||||
{
|
||||
if (debug_disabled) return;
|
||||
if (!idevicerestore_debug) {
|
||||
return;
|
||||
}
|
||||
thread_once(&init_once, _log_init);
|
||||
mutex_lock(&log_mutex);
|
||||
va_list vargs;
|
||||
va_start(vargs, format);
|
||||
vfprintf((debug_stream) ? debug_stream : stderr, format, vargs);
|
||||
va_end(vargs);
|
||||
fflush(debug_stream?debug_stream:stderr);
|
||||
mutex_unlock(&log_mutex);
|
||||
}
|
||||
|
||||
void idevicerestore_set_info_stream(FILE* strm)
|
||||
{
|
||||
if (strm) {
|
||||
info_disabled = 0;
|
||||
info_stream = strm;
|
||||
} else {
|
||||
info_disabled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void idevicerestore_set_error_stream(FILE* strm)
|
||||
{
|
||||
if (strm) {
|
||||
error_disabled = 0;
|
||||
error_stream = strm;
|
||||
} else {
|
||||
error_disabled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void idevicerestore_set_debug_stream(FILE* strm)
|
||||
{
|
||||
if (strm) {
|
||||
debug_disabled = 0;
|
||||
debug_stream = strm;
|
||||
} else {
|
||||
debug_disabled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
const char* idevicerestore_get_error(void)
|
||||
{
|
||||
if (idevicerestore_err_buff[0] == 0) {
|
||||
return NULL;
|
||||
} else {
|
||||
char* p = NULL;
|
||||
while ((strlen(idevicerestore_err_buff) > 0) && (p = strrchr(idevicerestore_err_buff, '\n'))) {
|
||||
p[0] = '\0';
|
||||
}
|
||||
return (const char*)idevicerestore_err_buff;
|
||||
}
|
||||
}
|
||||
static void (*banner_func)(const char*) = NULL;
|
||||
static void (*banner_hide_func)(void) = NULL;
|
||||
|
||||
int write_file(const char* filename, const void* data, size_t size) {
|
||||
size_t bytes = 0;
|
||||
FILE* file = NULL;
|
||||
|
||||
debug("Writing data to %s\n", filename);
|
||||
logger(LL_DEBUG, "Writing data to %s\n", filename);
|
||||
file = fopen(filename, "wb");
|
||||
if (file == NULL) {
|
||||
error("write_file: Unable to open file %s\n", filename);
|
||||
logger(LL_ERROR, "write_file: Unable to open file %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -192,7 +95,7 @@ int write_file(const char* filename, const void* data, size_t size) {
|
||||
fclose(file);
|
||||
|
||||
if (bytes != size) {
|
||||
error("ERROR: Unable to write entire file: %s: %d of %d\n", filename, (int)bytes, (int)size);
|
||||
logger(LL_ERROR, "Unable to write entire file: %s: %d of %d\n", filename, (int)bytes, (int)size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -206,26 +109,26 @@ int read_file(const char* filename, void** data, size_t* size) {
|
||||
char* buffer = NULL;
|
||||
struct stat fst;
|
||||
|
||||
debug("Reading data from %s\n", filename);
|
||||
logger(LL_DEBUG, "Reading data from %s\n", filename);
|
||||
|
||||
*size = 0;
|
||||
*data = NULL;
|
||||
|
||||
file = fopen(filename, "rb");
|
||||
if (file == NULL) {
|
||||
error("read_file: cannot open %s: %s\n", filename, strerror(errno));
|
||||
logger(LL_ERROR, "read_file: cannot open %s: %s\n", filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fstat(fileno(file), &fst) < 0) {
|
||||
error("read_file: fstat: %s\n", strerror(errno));
|
||||
logger(LL_ERROR, "read_file: fstat: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
length = fst.st_size;
|
||||
|
||||
buffer = (char*) malloc(length);
|
||||
if (buffer == NULL) {
|
||||
error("ERROR: Out of memory\n");
|
||||
logger(LL_ERROR, "Out of memory\n");
|
||||
fclose(file);
|
||||
return -1;
|
||||
}
|
||||
@@ -233,7 +136,7 @@ int read_file(const char* filename, void** data, size_t* size) {
|
||||
fclose(file);
|
||||
|
||||
if (bytes != length) {
|
||||
error("ERROR: Unable to read entire file\n");
|
||||
logger(LL_ERROR, "Unable to read entire file\n");
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
@@ -243,32 +146,309 @@ int read_file(const char* filename, void** data, size_t* size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void debug_plist(plist_t plist) {
|
||||
uint32_t size = 0;
|
||||
char* data = NULL;
|
||||
plist_to_xml(plist, &data, &size);
|
||||
if (size <= MAX_PRINT_LEN)
|
||||
info("printing %i bytes plist:\n%s", size, data);
|
||||
else
|
||||
info("supressed printing %i bytes plist...\n", size);
|
||||
free(data);
|
||||
int process_text_lines(const char* text, int maxwidth, struct tuple** lines_out, int* maxlen_out)
|
||||
{
|
||||
if (!text) return 0;
|
||||
int len = strlen(text);
|
||||
int numlines = 0;
|
||||
int maxlen = 0;
|
||||
int linestart = 0;
|
||||
int linelen = 0;
|
||||
int lastspace = 0;
|
||||
int maxlines = 8;
|
||||
int count = 0;
|
||||
struct tuple* lines = (struct tuple*)malloc(sizeof(struct tuple) * maxlines);
|
||||
int i = 0;
|
||||
while (i <= len) {
|
||||
int split_line = 0;
|
||||
if ((text[i] & 0xE0) == 0xC0) i += 1;
|
||||
else if ((text[i] & 0xF0) == 0xE0) i += 2;
|
||||
else if ((text[i] & 0xF8) == 0xF0) i += 3;
|
||||
if (i > len) i = len;
|
||||
linelen = i - linestart;
|
||||
if (text[i] == '\0') {
|
||||
split_line = 1;
|
||||
}
|
||||
if (linelen > maxwidth) {
|
||||
if (lastspace > linestart+maxwidth/2+6) {
|
||||
count -= i-lastspace;
|
||||
i = lastspace;
|
||||
linelen = i - linestart;
|
||||
split_line = 1;
|
||||
} else {
|
||||
split_line = 1;
|
||||
}
|
||||
}
|
||||
if ((linelen > 0 && split_line) || text[i] == '\n') {
|
||||
split_line = 0;
|
||||
if (numlines == maxlines) {
|
||||
maxlines += 8;
|
||||
struct tuple* newlines = (struct tuple*)realloc(lines, sizeof(struct tuple) * maxlines);
|
||||
if (!newlines) {
|
||||
printf("FATAL: Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
lines = newlines;
|
||||
}
|
||||
lines[numlines].idx = linestart;
|
||||
lines[numlines].len = linelen;
|
||||
lines[numlines].plen = count;
|
||||
if (count > maxlen) maxlen = count;
|
||||
numlines++;
|
||||
linestart = i+1;
|
||||
count = 0;
|
||||
}
|
||||
else if (text[i] == ' ') {
|
||||
lastspace = i;
|
||||
count++;
|
||||
} else {
|
||||
count++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
*lines_out = lines;
|
||||
*maxlen_out = maxlen;
|
||||
return numlines;
|
||||
}
|
||||
|
||||
void print_progress_bar(double progress) {
|
||||
#ifndef WIN32
|
||||
if (info_disabled) return;
|
||||
int i = 0;
|
||||
if(progress < 0) return;
|
||||
if(progress > 100) progress = 100;
|
||||
fprintf((info_stream) ? info_stream : stdout, "\r[");
|
||||
for(i = 0; i < 50; i++) {
|
||||
if(i < progress / 2) fprintf((info_stream) ? info_stream : stdout, "=");
|
||||
else fprintf((info_stream) ? info_stream : stdout, " ");
|
||||
void set_banner_funcs(void (*showfunc)(const char*), void (*hidefunc)(void))
|
||||
{
|
||||
banner_func = showfunc;
|
||||
banner_hide_func = hidefunc;
|
||||
}
|
||||
|
||||
void show_banner(const char* text)
|
||||
{
|
||||
if (banner_func) {
|
||||
banner_func(text);
|
||||
} else {
|
||||
int i;
|
||||
int maxlen = 0;
|
||||
struct tuple* lines = NULL;
|
||||
int numlines = process_text_lines(text, 74, &lines, &maxlen);
|
||||
printf("%.*s\n", maxlen + 4, STARS);
|
||||
for (i = 0; i < numlines; i++) {
|
||||
printf("* %.*s%.*s *\n", lines[i].len, text + lines[i].idx, maxlen-lines[i].plen, SPACES);
|
||||
}
|
||||
printf("%.*s\n", maxlen + 4, STARS);
|
||||
free(lines);
|
||||
}
|
||||
fprintf((info_stream) ? info_stream : stdout, "] %5.1f%%", progress);
|
||||
if(progress >= 100) fprintf((info_stream) ? info_stream : stdout, "\n");
|
||||
fflush((info_stream) ? info_stream : stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
void hide_banner()
|
||||
{
|
||||
if (banner_hide_func) {
|
||||
banner_hide_func();
|
||||
}
|
||||
}
|
||||
|
||||
static int (*prompt_func)(const char* title, const char* text) = NULL;
|
||||
|
||||
void set_prompt_func(int (*func)(const char* title, const char* text))
|
||||
{
|
||||
prompt_func = func;
|
||||
}
|
||||
|
||||
int prompt_user(const char* title, const char* text)
|
||||
{
|
||||
if (!text) return -1;
|
||||
if (prompt_func) {
|
||||
return prompt_func(title, text);
|
||||
}
|
||||
int i;
|
||||
int result = 0;
|
||||
int maxlen = 0;
|
||||
struct tuple* lines = NULL;
|
||||
int numlines = process_text_lines(text, 74, &lines, &maxlen);
|
||||
int outerlen = maxlen+4;
|
||||
int titlelen = (title) ? strlen(title) : 0;
|
||||
if (titlelen > 0) {
|
||||
int lefttitlelen = (titlelen+4)/2;
|
||||
int righttitlelen = titlelen+4 - lefttitlelen;
|
||||
int leftpounds = outerlen/2 - lefttitlelen;
|
||||
int rightpounds = outerlen-(titlelen+4) - leftpounds;
|
||||
printf("%.*s[ %.*s ]%.*s\n", leftpounds, POUNDS, titlelen, title, rightpounds, POUNDS);
|
||||
} else {
|
||||
printf("%.*s\n", outerlen, POUNDS);
|
||||
}
|
||||
for (i = 0; i < numlines; i++) {
|
||||
printf("%c %.*s%.*s %c\n", *POUNDS, lines[i].len, text + lines[i].idx, maxlen-lines[i].plen, SPACES, *POUNDS);
|
||||
}
|
||||
free(lines);
|
||||
const char* yesmsg = "Type YES and press ENTER to continue, or hit CTRL+C to cancel.";
|
||||
int ylen = strlen(yesmsg);
|
||||
printf("%c %.*s%.*s %c\n", *POUNDS, ylen, yesmsg, maxlen-ylen, SPACES, *POUNDS);
|
||||
printf("%.*s\n", outerlen, POUNDS);
|
||||
|
||||
char input[64];
|
||||
while (1) {
|
||||
printf("> ");
|
||||
fflush(stdout);
|
||||
fflush(stdin);
|
||||
input[0] = '\0';
|
||||
get_user_input(input, 63, 0);
|
||||
if (global_quit_flag) {
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
if (*input != '\0' && !strcmp(input, "YES")) {
|
||||
result = 1;
|
||||
break;
|
||||
} else {
|
||||
printf("Invalid input. Please type YES or hit CTRL+C to abort.\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void (*update_progress_func)(struct progress_info_entry** list, int count) = NULL;
|
||||
static double progress_granularity = 0.001;
|
||||
|
||||
void set_update_progress_func(void (*func)(struct progress_info_entry** list, int count))
|
||||
{
|
||||
update_progress_func = func;
|
||||
}
|
||||
|
||||
void set_progress_granularity(double granularity)
|
||||
{
|
||||
progress_granularity = granularity;
|
||||
}
|
||||
|
||||
mutex_t prog_mutex;
|
||||
struct collection progress_info;
|
||||
thread_once_t progress_info_once = THREAD_ONCE_INIT;
|
||||
static void _init_progress_info(void)
|
||||
{
|
||||
mutex_init(&prog_mutex);
|
||||
collection_init(&progress_info);
|
||||
}
|
||||
|
||||
uint32_t progress_get_next_tag(void)
|
||||
{
|
||||
mutex_lock(&prog_mutex);
|
||||
uint32_t newtag = ++progress_unique_tag;
|
||||
mutex_unlock(&prog_mutex);
|
||||
return newtag;
|
||||
}
|
||||
|
||||
void progress_reset_tag(void)
|
||||
{
|
||||
progress_unique_tag = 1;
|
||||
}
|
||||
|
||||
void register_progress(uint32_t tag, const char* label)
|
||||
{
|
||||
thread_once(&progress_info_once, _init_progress_info);
|
||||
if (!label) {
|
||||
return;
|
||||
}
|
||||
mutex_lock(&prog_mutex);
|
||||
struct progress_info_entry* found = NULL;
|
||||
FOREACH(struct progress_info_entry* e, &progress_info) {
|
||||
if (e->tag == tag) {
|
||||
found = e;
|
||||
break;
|
||||
}
|
||||
} ENDFOREACH
|
||||
if (found) {
|
||||
if (strcmp(found->label, label) != 0) {
|
||||
free(found->label);
|
||||
found->label = strdup(label);
|
||||
if (update_progress_func) {
|
||||
update_progress_func((struct progress_info_entry**)(&progress_info)->list, progress_info.capacity);
|
||||
} else {
|
||||
print_progress_bar(found->label, found->progress);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&prog_mutex);
|
||||
return;
|
||||
}
|
||||
struct progress_info_entry* newinfo = (struct progress_info_entry*)calloc(1, sizeof(struct progress_info_entry));
|
||||
if (!newinfo) {
|
||||
logger(LL_ERROR, "Out of memory?!\n");
|
||||
exit(1);
|
||||
}
|
||||
newinfo->tag = tag;
|
||||
newinfo->label = strdup(label);
|
||||
newinfo->progress = 0;
|
||||
collection_add(&progress_info, newinfo);
|
||||
if (update_progress_func) {
|
||||
update_progress_func((struct progress_info_entry**)(&progress_info)->list, progress_info.capacity);
|
||||
} else {
|
||||
print_progress_bar(newinfo->label, newinfo->progress);
|
||||
}
|
||||
mutex_unlock(&prog_mutex);
|
||||
}
|
||||
|
||||
void finalize_progress(uint32_t tag)
|
||||
{
|
||||
mutex_lock(&prog_mutex);
|
||||
struct progress_info_entry* found = NULL;
|
||||
FOREACH(struct progress_info_entry* e, &progress_info) {
|
||||
if (e->tag == tag) {
|
||||
found = e;
|
||||
break;
|
||||
}
|
||||
} ENDFOREACH
|
||||
if (!found) {
|
||||
mutex_unlock(&prog_mutex);
|
||||
return;
|
||||
}
|
||||
collection_remove(&progress_info, found);
|
||||
free(found->label);
|
||||
free(found);
|
||||
if (update_progress_func) {
|
||||
update_progress_func((struct progress_info_entry**)(&progress_info)->list, progress_info.capacity);
|
||||
}
|
||||
mutex_unlock(&prog_mutex);
|
||||
}
|
||||
|
||||
void print_progress_bar(const char* prefix, double progress)
|
||||
{
|
||||
int i = 0;
|
||||
if (progress < 0) return;
|
||||
if (progress > 1) progress = 1;
|
||||
if (prefix) {
|
||||
printf("\r%s [", prefix);
|
||||
} else {
|
||||
printf("\r[");
|
||||
}
|
||||
for (i = 0; i < 50; i++) {
|
||||
if (i < (int)(progress*50.0)) printf("=");
|
||||
else printf(" ");
|
||||
}
|
||||
printf("] %5.1f%% ", progress*100.0);
|
||||
if (progress >= 1) printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void set_progress(uint32_t tag, double progress)
|
||||
{
|
||||
mutex_lock(&prog_mutex);
|
||||
struct progress_info_entry* found = NULL;
|
||||
FOREACH(struct progress_info_entry* e, &progress_info) {
|
||||
if (e->tag == tag) {
|
||||
found = e;
|
||||
break;
|
||||
}
|
||||
} ENDFOREACH
|
||||
if (!found) {
|
||||
mutex_unlock(&prog_mutex);
|
||||
return;
|
||||
}
|
||||
if (progress < 0) progress = 0;
|
||||
if (progress > 1.0) progress = 1.0;
|
||||
found->progress = progress;
|
||||
if ((progress == 0) || (found->progress - found->lastprog >= progress_granularity)) {
|
||||
if (update_progress_func) {
|
||||
update_progress_func((struct progress_info_entry**)(&progress_info)->list, progress_info.capacity);
|
||||
} else {
|
||||
print_progress_bar(found->label, found->progress);
|
||||
}
|
||||
found->lastprog = found->progress;
|
||||
}
|
||||
mutex_unlock(&prog_mutex);
|
||||
}
|
||||
|
||||
#define GET_RAND(min, max) ((rand() % (max - min)) + min)
|
||||
@@ -485,17 +665,14 @@ char *get_temp_filename(const char *prefix)
|
||||
|
||||
void idevicerestore_progress(struct idevicerestore_client_t* client, int step, double progress)
|
||||
{
|
||||
thread_once(&init_once, _log_init);
|
||||
mutex_lock(&log_mutex);
|
||||
if(client && client->progress_cb) {
|
||||
client->progress_cb(step, progress, client->progress_cb_data);
|
||||
} else {
|
||||
// we don't want to be too verbose in regular idevicerestore.
|
||||
if ((step == RESTORE_STEP_UPLOAD_FS) || (step == RESTORE_STEP_VERIFY_FS) || (step == RESTORE_STEP_FLASH_FW) || (step == RESTORE_STEP_UPLOAD_IMG)) {
|
||||
print_progress_bar(100.0 * progress);
|
||||
print_progress_bar(NULL, progress);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&log_mutex);
|
||||
}
|
||||
|
||||
#ifndef HAVE_STRSEP
|
||||
|
||||
+32
-8
@@ -40,6 +40,7 @@ extern "C" {
|
||||
#include <libimobiledevice-glue/thread.h>
|
||||
|
||||
#include "idevicerestore.h"
|
||||
#include "log.h"
|
||||
|
||||
#define _MODE_UNKNOWN 0
|
||||
#define _MODE_WTF 1
|
||||
@@ -140,19 +141,42 @@ struct idevicerestore_client_t {
|
||||
int async_err;
|
||||
};
|
||||
|
||||
extern int global_quit_flag;
|
||||
|
||||
extern struct idevicerestore_mode_t idevicerestore_modes[];
|
||||
|
||||
extern int idevicerestore_debug;
|
||||
|
||||
__attribute__((format(printf, 1, 2)))
|
||||
void info(const char* format, ...);
|
||||
__attribute__((format(printf, 1, 2)))
|
||||
void error(const char* format, ...);
|
||||
__attribute__((format(printf, 1, 2)))
|
||||
void debug(const char* format, ...);
|
||||
void set_banner_funcs(void (*showfunc)(const char*), void (*hidefunc)(void));
|
||||
void show_banner(const char* text);
|
||||
void hide_banner();
|
||||
|
||||
struct progress_info_entry {
|
||||
uint32_t tag;
|
||||
char* label;
|
||||
double progress;
|
||||
int lastprog;
|
||||
};
|
||||
void set_update_progress_func(void (*func)(struct progress_info_entry** list, int count));
|
||||
void set_progress_granularity(double granularity);
|
||||
uint32_t progress_get_next_tag(void);
|
||||
void progress_reset_tag(void);
|
||||
void register_progress(uint32_t tag, const char* label);
|
||||
void set_progress(uint32_t tag, double progress);
|
||||
void finalize_progress(uint32_t tag);
|
||||
void print_progress_bar(const char* prefix, double progress);
|
||||
|
||||
struct tuple {
|
||||
int idx;
|
||||
int len;
|
||||
int plen;
|
||||
};
|
||||
|
||||
int process_text_lines(const char* text, int maxwidth, struct tuple** lines_out, int* maxlen_out);
|
||||
|
||||
void set_prompt_func(int (*func)(const char* title, const char* text));
|
||||
int prompt_user(const char* title, const char* message);
|
||||
|
||||
void debug_plist(plist_t plist);
|
||||
void print_progress_bar(double progress);
|
||||
int read_file(const char* filename, void** data, size_t* size);
|
||||
int write_file(const char* filename, const void* data, size_t size);
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
static int dfu_progress_callback(irecv_client_t client, const irecv_event_t* event) {
|
||||
if (event->type == IRECV_PROGRESS) {
|
||||
print_progress_bar(event->progress);
|
||||
set_progress('DFUP', (double)event->progress/100.0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -49,24 +49,26 @@ int dfu_client_new(struct idevicerestore_client_t* client)
|
||||
client->dfu = (struct dfu_client_t*)malloc(sizeof(struct dfu_client_t));
|
||||
memset(client->dfu, 0, sizeof(struct dfu_client_t));
|
||||
if (client->dfu == NULL) {
|
||||
error("ERROR: Out of memory\n");
|
||||
logger(LL_ERROR, "Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (irecv_open_with_ecid_and_attempts(&dfu, client->ecid, 10) != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to connect to device in DFU mode\n");
|
||||
logger(LL_ERROR, "Unable to connect to device in DFU mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
irecv_event_subscribe(dfu, IRECV_PROGRESS, &dfu_progress_callback, NULL);
|
||||
client->dfu->client = dfu;
|
||||
register_progress('DFUP', "Uploading");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dfu_client_free(struct idevicerestore_client_t* client)
|
||||
{
|
||||
if(client != NULL) {
|
||||
finalize_progress('DFUP');
|
||||
if (client->dfu != NULL) {
|
||||
if(client->dfu->client != NULL) {
|
||||
irecv_close(client->dfu->client);
|
||||
@@ -107,11 +109,11 @@ int dfu_send_buffer_with_options(struct idevicerestore_client_t* client, unsigne
|
||||
{
|
||||
irecv_error_t err = 0;
|
||||
|
||||
info("Sending data (%d bytes)...\n", size);
|
||||
logger(LL_INFO, "Sending data (%d bytes)...\n", size);
|
||||
|
||||
err = irecv_send_buffer(client->dfu->client, buffer, size, irecv_options);
|
||||
if (err != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to send data: %s\n", irecv_strerror(err));
|
||||
logger(LL_ERROR, "Unable to send data: %s\n", irecv_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -144,19 +146,19 @@ int dfu_send_component(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
} else {
|
||||
if (tss) {
|
||||
if (tss_response_get_path_by_entry(tss, component, &path) < 0) {
|
||||
debug("NOTE: No path for component %s in TSS, will fetch from build_identity\n", component);
|
||||
logger(LL_DEBUG, "No path for component %s in TSS, will fetch from build_identity\n", component);
|
||||
}
|
||||
}
|
||||
if (!path) {
|
||||
if (build_identity_get_component_path(build_identity, component, &path) < 0) {
|
||||
error("ERROR: Unable to get path for component '%s'\n", component);
|
||||
logger(LL_ERROR, "Unable to get path for component '%s'\n", component);
|
||||
free(path);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (extract_component(client->ipsw, path, &component_data, &component_size) < 0) {
|
||||
error("ERROR: Unable to extract component: %s\n", component);
|
||||
logger(LL_ERROR, "Unable to extract component: %s\n", component);
|
||||
free(path);
|
||||
return -1;
|
||||
}
|
||||
@@ -168,7 +170,7 @@ int dfu_send_component(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
uint32_t size = 0;
|
||||
|
||||
if (personalize_component(client, component, component_data, component_size, tss, &data, &size) < 0) {
|
||||
error("ERROR: Unable to get personalized component: %s\n", component);
|
||||
logger(LL_ERROR, "Unable to get personalized component: %s\n", component);
|
||||
free(component_data);
|
||||
return -1;
|
||||
}
|
||||
@@ -179,14 +181,14 @@ int dfu_send_component(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
unsigned char* ticket = NULL;
|
||||
unsigned int tsize = 0;
|
||||
if (tss_response_get_ap_ticket(client->tss, &ticket, &tsize) < 0) {
|
||||
error("ERROR: Unable to get ApTicket from TSS request\n");
|
||||
logger(LL_ERROR, "Unable to get ApTicket from TSS request\n");
|
||||
return -1;
|
||||
}
|
||||
uint32_t fillsize = 0;
|
||||
if (tsize % 64 != 0) {
|
||||
fillsize = ((tsize / 64) + 1) * 64;
|
||||
}
|
||||
debug("ticket size = %d\nfillsize = %d\n", tsize, fillsize);
|
||||
logger(LL_DEBUG, "ticket size = %d\nfillsize = %d\n", tsize, fillsize);
|
||||
unsigned char* newdata = (unsigned char*)malloc(size + fillsize);
|
||||
memcpy(newdata, ticket, tsize);
|
||||
memset(newdata + tsize, '\xFF', fillsize - tsize);
|
||||
@@ -196,11 +198,11 @@ int dfu_send_component(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
size += fillsize;
|
||||
}
|
||||
|
||||
info("Sending %s (%d bytes)...\n", component, size);
|
||||
logger(LL_INFO, "Sending %s (%d bytes)...\n", component, size);
|
||||
|
||||
irecv_error_t err = irecv_send_buffer(client->dfu->client, data, size, IRECV_SEND_OPT_DFU_NOTIFY_FINISH);
|
||||
if (err != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to send %s component: %s\n", component, irecv_strerror(err));
|
||||
logger(LL_ERROR, "Unable to send %s component: %s\n", component, irecv_strerror(err));
|
||||
free(data);
|
||||
return -1;
|
||||
}
|
||||
@@ -366,14 +368,14 @@ int dfu_send_component_and_command(struct idevicerestore_client_t* client, plist
|
||||
irecv_error_t dfu_error = IRECV_E_SUCCESS;
|
||||
|
||||
if (dfu_send_component(client, build_identity, component) < 0) {
|
||||
error("ERROR: Unable to send %s to device.\n", component);
|
||||
logger(LL_ERROR, "Unable to send %s to device.\n", component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
info("INFO: executing command: %s\n", command);
|
||||
logger(LL_INFO, "INFO: executing command: %s\n", command);
|
||||
dfu_error = irecv_send_command(client->dfu->client, command);
|
||||
if (dfu_error != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to execute %s\n", command);
|
||||
logger(LL_ERROR, "Unable to execute %s\n", command);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -384,10 +386,10 @@ int dfu_send_command(struct idevicerestore_client_t* client, const char* command
|
||||
{
|
||||
irecv_error_t dfu_error = IRECV_E_SUCCESS;
|
||||
|
||||
info("INFO: executing command: %s\n", command);
|
||||
logger(LL_INFO, "INFO: executing command: %s\n", command);
|
||||
dfu_error = irecv_send_command(client->dfu->client, command);
|
||||
if (dfu_error != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to execute %s\n", command);
|
||||
logger(LL_ERROR, "Unable to execute %s\n", command);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -398,7 +400,7 @@ int dfu_send_iboot_stage1_components(struct idevicerestore_client_t* client, pli
|
||||
{
|
||||
plist_t manifest_node = plist_dict_get_item(build_identity, "Manifest");
|
||||
if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) {
|
||||
error("ERROR: Unable to find manifest node\n");
|
||||
logger(LL_ERROR, "Unable to find manifest node\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -422,12 +424,12 @@ int dfu_send_iboot_stage1_components(struct idevicerestore_client_t* client, pli
|
||||
uint8_t b = 0;
|
||||
plist_get_bool_val(iboot_node, &b);
|
||||
if (b) {
|
||||
debug("DEBUG: %s is loaded by iBoot Stage 1 and iBoot.\n", key);
|
||||
logger(LL_DEBUG, "%s is loaded by iBoot Stage 1 and iBoot.\n", key);
|
||||
} else {
|
||||
debug("DEBUG: %s is loaded by iBoot Stage 1 but not iBoot...\n", key);
|
||||
logger(LL_DEBUG, "%s is loaded by iBoot Stage 1 but not iBoot...\n", key);
|
||||
}
|
||||
if (dfu_send_component_and_command(client, build_identity, key, "firmware") < 0) {
|
||||
error("ERROR: Unable to send component '%s' to device.\n", key);
|
||||
logger(LL_ERROR, "Unable to send component '%s' to device.\n", key);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
@@ -443,14 +445,14 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
int mode = 0;
|
||||
|
||||
if (dfu_client_new(client) < 0) {
|
||||
error("ERROR: Unable to connect to DFU device\n");
|
||||
logger(LL_ERROR, "Unable to connect to DFU device\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
irecv_get_mode(client->dfu->client, &mode);
|
||||
|
||||
if (mode != IRECV_K_DFU_MODE) {
|
||||
info("NOTE: device is not in DFU mode, assuming recovery mode.\n");
|
||||
logger(LL_NOTICE, "device is not in DFU mode, assuming recovery mode.\n");
|
||||
client->mode = MODE_RECOVERY;
|
||||
return 0;
|
||||
}
|
||||
@@ -458,7 +460,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
mutex_lock(&client->device_event_mutex);
|
||||
|
||||
if (dfu_send_component(client, build_identity, "iBSS") < 0) {
|
||||
error("ERROR: Unable to send iBSS to device\n");
|
||||
logger(LL_ERROR, "Unable to send iBSS to device\n");
|
||||
irecv_close(client->dfu->client);
|
||||
client->dfu->client = NULL;
|
||||
return -1;
|
||||
@@ -467,21 +469,21 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
|
||||
if (client->build_major > 8) {
|
||||
/* reconnect */
|
||||
debug("Waiting for device to disconnect...\n");
|
||||
logger(LL_DEBUG, "Waiting for device to disconnect...\n");
|
||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
||||
if (client->mode != MODE_UNKNOWN || (client->flags & FLAG_QUIT)) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
if (!(client->flags & FLAG_QUIT)) {
|
||||
error("ERROR: Device did not disconnect. Possibly invalid iBSS. Reset device and try again.\n");
|
||||
logger(LL_ERROR, "Device did not disconnect. Possibly invalid iBSS. Reset device and try again.\n");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
debug("Waiting for device to reconnect...\n");
|
||||
logger(LL_DEBUG, "Waiting for device to reconnect...\n");
|
||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
||||
if ((client->mode != MODE_DFU && client->mode != MODE_RECOVERY) || (client->flags & FLAG_QUIT)) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
if (!(client->flags & FLAG_QUIT)) {
|
||||
error("ERROR: Device did not reconnect in DFU or recovery mode. Possibly invalid iBSS. Reset device and try again.\n");
|
||||
logger(LL_ERROR, "Device did not reconnect in DFU or recovery mode. Possibly invalid iBSS. Reset device and try again.\n");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -493,7 +495,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
unsigned int nonce_size = 0;
|
||||
int nonce_changed = 0;
|
||||
if (dfu_get_ap_nonce(client, &nonce, &nonce_size) < 0) {
|
||||
error("ERROR: Unable to get ApNonce from device!\n");
|
||||
logger(LL_ERROR, "Unable to get ApNonce from device!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -508,29 +510,25 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
free(nonce);
|
||||
}
|
||||
|
||||
info("Nonce: ");
|
||||
int i;
|
||||
for (i = 0; i < client->nonce_size; i++) {
|
||||
info("%02x ", client->nonce[i]);
|
||||
}
|
||||
info("\n");
|
||||
logger(LL_INFO, "Nonce: ");
|
||||
logger_dump_hex(LL_INFO, client->nonce, client->nonce_size);
|
||||
|
||||
if (nonce_changed && !(client->flags & FLAG_CUSTOM)) {
|
||||
// Welcome iOS5. We have to re-request the TSS with our nonce.
|
||||
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");
|
||||
logger(LL_ERROR, "Unable to get SHSH blobs for this device\n");
|
||||
return -1;
|
||||
}
|
||||
if (!client->tss) {
|
||||
error("ERROR: can't continue without TSS\n");
|
||||
logger(LL_ERROR, "can't continue without TSS\n");
|
||||
return -1;
|
||||
}
|
||||
fixup_tss(client->tss);
|
||||
}
|
||||
|
||||
if (irecv_usb_set_configuration(client->dfu->client, 1) < 0) {
|
||||
error("ERROR: set configuration failed\n");
|
||||
logger(LL_ERROR, "set configuration failed\n");
|
||||
}
|
||||
|
||||
mutex_lock(&client->device_event_mutex);
|
||||
@@ -540,7 +538,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
// Without this empty policy file & its special signature, iBEC won't start.
|
||||
if (dfu_send_component_and_command(client, build_identity, "Ap,LocalPolicy", "lpolrestore") < 0) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Unable to send Ap,LocalPolicy to device\n");
|
||||
logger(LL_ERROR, "Unable to send Ap,LocalPolicy to device\n");
|
||||
irecv_close(client->dfu->client);
|
||||
client->dfu->client = NULL;
|
||||
return -1;
|
||||
@@ -553,17 +551,17 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
boot_stage = strtoul(value, NULL, 0);
|
||||
}
|
||||
if (boot_stage > 0) {
|
||||
info("iBoot boot-stage=%s\n", value);
|
||||
logger(LL_INFO, "iBoot boot-stage=%s\n", value);
|
||||
free(value);
|
||||
value = NULL;
|
||||
if (boot_stage != 1) {
|
||||
error("ERROR: iBoot should be at boot stage 1, continuing anyway...\n");
|
||||
logger(LL_ERROR, "iBoot should be at boot stage 1, continuing anyway...\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (dfu_send_iboot_stage1_components(client, build_identity) < 0) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Unable to send iBoot stage 1 components to device\n");
|
||||
logger(LL_ERROR, "Unable to send iBoot stage 1 components to device\n");
|
||||
irecv_close(client->dfu->client);
|
||||
client->dfu->client = NULL;
|
||||
return -1;
|
||||
@@ -571,7 +569,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
|
||||
if (dfu_send_command(client, "setenv auto-boot false") < 0) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Unable to send command to device\n");
|
||||
logger(LL_ERROR, "Unable to send command to device\n");
|
||||
irecv_close(client->dfu->client);
|
||||
client->dfu->client = NULL;
|
||||
return -1;
|
||||
@@ -579,7 +577,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
|
||||
if (dfu_send_command(client, "saveenv") < 0) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Unable to send command to device\n");
|
||||
logger(LL_ERROR, "Unable to send command to device\n");
|
||||
irecv_close(client->dfu->client);
|
||||
client->dfu->client = NULL;
|
||||
return -1;
|
||||
@@ -587,7 +585,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
|
||||
if (dfu_send_command(client, "setenvnp boot-args rd=md0 nand-enable-reformat=1 -progress -restore") < 0) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Unable to send command to device\n");
|
||||
logger(LL_ERROR, "Unable to send command to device\n");
|
||||
irecv_close(client->dfu->client);
|
||||
client->dfu->client = NULL;
|
||||
return -1;
|
||||
@@ -595,7 +593,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
|
||||
if (dfu_send_component(client, build_identity, "RestoreLogo") < 0) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Unable to send RestoreDCP to device\n");
|
||||
logger(LL_ERROR, "Unable to send RestoreDCP to device\n");
|
||||
irecv_close(client->dfu->client);
|
||||
client->dfu->client = NULL;
|
||||
return -1;
|
||||
@@ -603,7 +601,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
|
||||
if (dfu_send_command(client, "setpicture 4") < 0) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Unable to send command to device\n");
|
||||
logger(LL_ERROR, "Unable to send command to device\n");
|
||||
irecv_close(client->dfu->client);
|
||||
client->dfu->client = NULL;
|
||||
return -1;
|
||||
@@ -611,7 +609,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
|
||||
if (dfu_send_command(client, "bgcolor 0 0 0") < 0) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Unable to send command to device\n");
|
||||
logger(LL_ERROR, "Unable to send command to device\n");
|
||||
irecv_close(client->dfu->client);
|
||||
client->dfu->client = NULL;
|
||||
return -1;
|
||||
@@ -621,7 +619,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
/* send iBEC */
|
||||
if (dfu_send_component(client, build_identity, "iBEC") < 0) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Unable to send iBEC to device\n");
|
||||
logger(LL_ERROR, "Unable to send iBEC to device\n");
|
||||
irecv_close(client->dfu->client);
|
||||
client->dfu->client = NULL;
|
||||
return -1;
|
||||
@@ -631,7 +629,7 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
sleep(1);
|
||||
if (irecv_send_command_breq(client->dfu->client, "go", 1) != IRECV_E_SUCCESS) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Unable to execute iBEC\n");
|
||||
logger(LL_ERROR, "Unable to execute iBEC\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -642,28 +640,28 @@ int dfu_enter_recovery(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
dfu_client_free(client);
|
||||
}
|
||||
|
||||
debug("Waiting for device to disconnect...\n");
|
||||
logger(LL_DEBUG, "Waiting for device to disconnect...\n");
|
||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
||||
if (client->mode != MODE_UNKNOWN || (client->flags & FLAG_QUIT)) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
if (!(client->flags & FLAG_QUIT)) {
|
||||
error("ERROR: Device did not disconnect. Possibly invalid %s. Reset device and try again.\n", (client->build_major > 8) ? "iBEC" : "iBSS");
|
||||
logger(LL_ERROR, "Device did not disconnect. Possibly invalid %s. Reset device and try again.\n", (client->build_major > 8) ? "iBEC" : "iBSS");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
debug("Waiting for device to reconnect in recovery mode...\n");
|
||||
logger(LL_DEBUG, "Waiting for device to reconnect in recovery mode...\n");
|
||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
||||
if (client->mode != MODE_RECOVERY || (client->flags & FLAG_QUIT)) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
if (!(client->flags & FLAG_QUIT)) {
|
||||
error("ERROR: Device did not reconnect in recovery mode. Possibly invalid %s. Reset device and try again.\n", (client->build_major > 8) ? "iBEC" : "iBSS");
|
||||
logger(LL_ERROR, "Device did not reconnect in recovery mode. Possibly invalid %s. Reset device and try again.\n", (client->build_major > 8) ? "iBEC" : "iBSS");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
|
||||
if (recovery_client_new(client) < 0) {
|
||||
error("ERROR: Unable to connect to recovery device\n");
|
||||
logger(LL_ERROR, "Unable to connect to recovery device\n");
|
||||
if (client->recovery->client) {
|
||||
irecv_close(client->recovery->client);
|
||||
client->recovery->client = NULL;
|
||||
|
||||
+21
-16
@@ -48,7 +48,7 @@ int download_to_buffer(const char* url, char** buf, uint32_t* length)
|
||||
int res = 0;
|
||||
CURL* handle = curl_easy_init();
|
||||
if (handle == NULL) {
|
||||
error("ERROR: could not initialize CURL\n");
|
||||
logger(LL_ERROR, "could not initialize CURL\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ int download_to_buffer(const char* url, char** buf, uint32_t* length)
|
||||
response.content = malloc(1);
|
||||
response.content[0] = '\0';
|
||||
|
||||
if (idevicerestore_debug)
|
||||
if (log_level >= LL_DEBUG)
|
||||
curl_easy_setopt(handle, CURLOPT_VERBOSE, 1);
|
||||
|
||||
/* disable SSL verification to allow download from untrusted https locations */
|
||||
@@ -86,17 +86,14 @@ int download_to_buffer(const char* url, char** buf, uint32_t* length)
|
||||
return res;
|
||||
}
|
||||
|
||||
static int lastprogress = 0;
|
||||
|
||||
static int download_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
|
||||
{
|
||||
double p = (dlnow / dltotal) * 100;
|
||||
double p = (dlnow / dltotal);
|
||||
|
||||
if (p < 100.0) {
|
||||
if ((int)p > lastprogress) {
|
||||
info("downloading: %d%%\n", (int)p);
|
||||
lastprogress = (int)p;
|
||||
}
|
||||
set_progress('DNLD', p);
|
||||
|
||||
if (global_quit_flag > 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -107,19 +104,17 @@ int download_to_file(const char* url, const char* filename, int enable_progress)
|
||||
int res = 0;
|
||||
CURL* handle = curl_easy_init();
|
||||
if (handle == NULL) {
|
||||
error("ERROR: could not initialize CURL\n");
|
||||
logger(LL_ERROR, "Could not initialize CURL\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE* f = fopen(filename, "wb");
|
||||
if (!f) {
|
||||
error("ERROR: cannot open '%s' for writing\n", filename);
|
||||
logger(LL_ERROR, "Cannot open '%s' for writing\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lastprogress = 0;
|
||||
|
||||
if (idevicerestore_debug)
|
||||
if (log_level >= LL_DEBUG)
|
||||
curl_easy_setopt(handle, CURLOPT_VERBOSE, 1);
|
||||
|
||||
/* disable SSL verification to allow download from untrusted https locations */
|
||||
@@ -128,8 +123,10 @@ int download_to_file(const char* url, const char* filename, int enable_progress)
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, NULL);
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEDATA, f);
|
||||
|
||||
if (enable_progress > 0)
|
||||
if (enable_progress > 0) {
|
||||
register_progress('DNLD', "Downloading");
|
||||
curl_easy_setopt(handle, CURLOPT_PROGRESSFUNCTION, (curl_progress_callback)&download_progress);
|
||||
}
|
||||
|
||||
curl_easy_setopt(handle, CURLOPT_NOPROGRESS, enable_progress > 0 ? 0: 1);
|
||||
curl_easy_setopt(handle, CURLOPT_USERAGENT, USER_AGENT_STRING);
|
||||
@@ -137,6 +134,11 @@ int download_to_file(const char* url, const char* filename, int enable_progress)
|
||||
curl_easy_setopt(handle, CURLOPT_URL, url);
|
||||
|
||||
curl_easy_perform(handle);
|
||||
|
||||
if (enable_progress) {
|
||||
finalize_progress('DNLD');
|
||||
}
|
||||
|
||||
curl_easy_cleanup(handle);
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -151,6 +153,9 @@ int download_to_file(const char* url, const char* filename, int enable_progress)
|
||||
res = -1;
|
||||
remove(filename);
|
||||
}
|
||||
if (global_quit_flag > 0) {
|
||||
res = -2;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ int fdr_connect(idevice_t device, fdr_type_t type, fdr_client_t* fdr)
|
||||
|
||||
*fdr = NULL;
|
||||
|
||||
debug("Connecting to FDR client at port %u\n", port);
|
||||
logger(LL_DEBUG, "Connecting to FDR client at port %u\n", port);
|
||||
|
||||
for (i = 1; i <= attempts; i++) {
|
||||
device_error = idevice_connect(device, port, &connection);
|
||||
@@ -75,17 +75,17 @@ int fdr_connect(idevice_t device, fdr_type_t type, fdr_client_t* fdr)
|
||||
}
|
||||
|
||||
if (i >= attempts) {
|
||||
error("ERROR: Unable to connect to FDR client (%d)\n", device_error);
|
||||
logger(LL_ERROR, "Unable to connect to FDR client (%d)\n", device_error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sleep(2);
|
||||
debug("Retrying connection...\n");
|
||||
logger(LL_DEBUG, "Retrying connection...\n");
|
||||
}
|
||||
|
||||
fdr_client_t fdr_loc = calloc(1, sizeof(struct fdr_client));
|
||||
if (!fdr_loc) {
|
||||
error("ERROR: Unable to allocate memory\n");
|
||||
logger(LL_ERROR, "Unable to allocate memory\n");
|
||||
return -1;
|
||||
}
|
||||
fdr_loc->connection = connection;
|
||||
@@ -138,7 +138,7 @@ int fdr_poll_and_handle_message(fdr_client_t fdr)
|
||||
uint16_t cmd;
|
||||
|
||||
if (!fdr) {
|
||||
error("ERROR: Invalid FDR client\n");
|
||||
logger(LL_ERROR, "Invalid FDR client\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -149,32 +149,32 @@ int fdr_poll_and_handle_message(fdr_client_t fdr)
|
||||
if (device_error == IDEVICE_E_SUCCESS && bytes != sizeof(cmd))
|
||||
#endif
|
||||
{
|
||||
debug("FDR %p timeout waiting for command\n", fdr);
|
||||
logger(LL_DEBUG, "FDR %p timeout waiting for command\n", fdr);
|
||||
return 0;
|
||||
}
|
||||
else if (device_error != IDEVICE_E_SUCCESS) {
|
||||
if (fdr->connection) {
|
||||
error("ERROR: Unable to receive message from FDR %p (%d). %u/%u bytes\n", fdr, device_error, bytes, (uint32_t)sizeof(cmd));
|
||||
logger(LL_ERROR, "Unable to receive message from FDR %p (%d). %u/%u bytes\n", fdr, device_error, bytes, (uint32_t)sizeof(cmd));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cmd == FDR_SYNC_MSG) {
|
||||
debug("FDR %p got sync message\n", fdr);
|
||||
logger(LL_DEBUG, "FDR %p got sync message\n", fdr);
|
||||
return fdr_handle_sync_cmd(fdr);
|
||||
}
|
||||
|
||||
if (cmd == FDR_PROXY_MSG) {
|
||||
debug("FDR %p got proxy message\n", fdr);
|
||||
logger(LL_DEBUG, "FDR %p got proxy message\n", fdr);
|
||||
return fdr_handle_proxy_cmd(fdr);
|
||||
}
|
||||
|
||||
if (cmd == FDR_PLIST_MSG) {
|
||||
debug("FDR %p got plist message\n", fdr);
|
||||
logger(LL_DEBUG, "FDR %p got plist message\n", fdr);
|
||||
return fdr_handle_plist_cmd(fdr);
|
||||
}
|
||||
|
||||
error("WARNING: FDR %p received unknown packet %#x of size %u\n", fdr, cmd, bytes);
|
||||
logger(LL_WARNING, "FDR %p received unknown packet %#x of size %u\n", fdr, cmd, bytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -184,14 +184,14 @@ void *fdr_listener_thread(void *cdata)
|
||||
int res;
|
||||
|
||||
while (fdr && fdr->connection) {
|
||||
debug("FDR %p waiting for message...\n", fdr);
|
||||
logger(LL_DEBUG, "FDR %p waiting for message...\n", fdr);
|
||||
res = fdr_poll_and_handle_message(fdr);
|
||||
if (fdr->type == FDR_CTRL && res >= 0)
|
||||
continue; // main thread should always retry
|
||||
if (res != 0)
|
||||
break;
|
||||
}
|
||||
debug("FDR %p terminating...\n", fdr);
|
||||
logger(LL_DEBUG, "FDR %p terminating...\n", fdr);
|
||||
fdr_free(fdr);
|
||||
return (void *)(intptr_t)res;
|
||||
}
|
||||
@@ -204,26 +204,26 @@ static int fdr_receive_plist(fdr_client_t fdr, plist_t* data)
|
||||
|
||||
device_error = idevice_connection_receive(fdr->connection, (char*)&len, sizeof(len), &bytes);
|
||||
if (device_error != IDEVICE_E_SUCCESS) {
|
||||
error("ERROR: Unable to receive packet length from FDR (%d)\n", device_error);
|
||||
logger(LL_ERROR, "Unable to receive packet length from FDR (%d)\n", device_error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = calloc(1, len);
|
||||
if (!buf) {
|
||||
error("ERROR: Unable to allocate memory for FDR receive buffer\n");
|
||||
logger(LL_ERROR, "Unable to allocate memory for FDR receive buffer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
device_error = idevice_connection_receive(fdr->connection, buf, len, &bytes);
|
||||
if (device_error != IDEVICE_E_SUCCESS) {
|
||||
error("ERROR: Unable to receive data from FDR\n");
|
||||
logger(LL_ERROR, "Unable to receive data from FDR\n");
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
plist_from_bin(buf, bytes, data);
|
||||
free(buf);
|
||||
|
||||
debug("FDR Received %d bytes\n", bytes);
|
||||
logger(LL_DEBUG, "FDR Received %d bytes\n", bytes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -241,12 +241,11 @@ static int fdr_send_plist(fdr_client_t fdr, plist_t data)
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
debug("FDR sending %d bytes:\n", len);
|
||||
if (idevicerestore_debug)
|
||||
debug_plist(data);
|
||||
logger(LL_DEBUG, "FDR sending %d bytes:\n", len);
|
||||
logger_dump_plist(LL_DEBUG, data, 1);
|
||||
device_error = idevice_connection_send(fdr->connection, (char *)&len, sizeof(len), &bytes);
|
||||
if (device_error != IDEVICE_E_SUCCESS || bytes != sizeof(len)) {
|
||||
error("ERROR: FDR unable to send data length. (%d) Sent %u of %u bytes.\n",
|
||||
logger(LL_ERROR, "FDR unable to send data length. (%d) Sent %u of %u bytes.\n",
|
||||
device_error, bytes, (uint32_t)sizeof(len));
|
||||
free(buf);
|
||||
return -1;
|
||||
@@ -254,12 +253,12 @@ static int fdr_send_plist(fdr_client_t fdr, plist_t data)
|
||||
device_error = idevice_connection_send(fdr->connection, buf, len, &bytes);
|
||||
free(buf);
|
||||
if (device_error != IDEVICE_E_SUCCESS || bytes != len) {
|
||||
error("ERROR: FDR unable to send data (%d). Sent %u of %u bytes.\n",
|
||||
logger(LL_ERROR, "FDR unable to send data (%d). Sent %u of %u bytes.\n",
|
||||
device_error, bytes, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
debug("FDR Sent %d bytes\n", bytes);
|
||||
logger(LL_DEBUG, "FDR Sent %d bytes\n", bytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -270,18 +269,18 @@ static int fdr_ctrl_handshake(fdr_client_t fdr)
|
||||
plist_t dict, node;
|
||||
int res;
|
||||
|
||||
debug("About to do ctrl handshake\n");
|
||||
logger(LL_DEBUG, "About to do ctrl handshake\n");
|
||||
|
||||
ctrlprotoversion = 2;
|
||||
|
||||
device_error = idevice_connection_send(fdr->connection, CTRLCMD, len, &bytes);
|
||||
if (device_error != IDEVICE_E_SUCCESS || bytes != len) {
|
||||
debug("Hmm... looks like the device doesn't like the newer protocol, using the old one\n");
|
||||
logger(LL_DEBUG, "Hmm... looks like the device doesn't like the newer protocol, using the old one\n");
|
||||
ctrlprotoversion = 1;
|
||||
len = sizeof(HELLOCTRLCMD);
|
||||
device_error = idevice_connection_send(fdr->connection, HELLOCTRLCMD, len, &bytes);
|
||||
if (device_error != IDEVICE_E_SUCCESS || bytes != len) {
|
||||
error("ERROR: FDR unable to send BeginCtrl. Sent %u of %u bytes.\n", bytes, len);
|
||||
logger(LL_ERROR, "FDR unable to send BeginCtrl. Sent %u of %u bytes.\n", bytes, len);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -293,21 +292,20 @@ static int fdr_ctrl_handshake(fdr_client_t fdr)
|
||||
res = fdr_send_plist(fdr, dict);
|
||||
plist_free(dict);
|
||||
if (res) {
|
||||
error("ERROR: FDR could not send Begin command.\n");
|
||||
logger(LL_ERROR, "FDR could not send Begin command.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fdr_receive_plist(fdr, &dict)) {
|
||||
error("ERROR: FDR did not get Begin command reply.\n");
|
||||
logger(LL_ERROR, "FDR did not get Begin command reply.\n");
|
||||
return -1;
|
||||
}
|
||||
if (idevicerestore_debug)
|
||||
debug_plist(dict);
|
||||
logger_dump_plist(LL_DEBUG, dict, 1);
|
||||
node = plist_dict_get_item(dict, "ConnPort");
|
||||
if (node && plist_get_node_type(node) == PLIST_UINT) {
|
||||
plist_get_uint_val(node, &conn_port);
|
||||
} else {
|
||||
error("ERROR: Could not get FDR ConnPort value\n");
|
||||
logger(LL_ERROR, "Could not get FDR ConnPort value\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -321,26 +319,26 @@ static int fdr_ctrl_handshake(fdr_client_t fdr)
|
||||
bytes = 0;
|
||||
device_error = idevice_connection_receive(fdr->connection, buf, 10, &bytes);
|
||||
if (device_error != IDEVICE_E_SUCCESS) {
|
||||
error("ERROR: Could not receive reply to HelloCtrl command\n");
|
||||
logger(LL_ERROR, "Could not receive reply to HelloCtrl command\n");
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(buf, "HelloCtrl", 10) != 0) {
|
||||
buf[9] = '\0';
|
||||
error("ERROR: Did not receive HelloCtrl as reply, but %s\n", buf);
|
||||
logger(LL_ERROR, "Did not receive HelloCtrl as reply, but %s\n", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes = 0;
|
||||
device_error = idevice_connection_receive(fdr->connection, (char*)&cport, 2, &bytes);
|
||||
if (device_error != IDEVICE_E_SUCCESS) {
|
||||
error("ERROR: Failed to receive conn port\n");
|
||||
logger(LL_ERROR, "Failed to receive conn port\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
conn_port = le16toh(cport);
|
||||
}
|
||||
|
||||
debug("Ctrl handshake done (ConnPort = %" PRIu64 ")\n", (uint64_t)conn_port);
|
||||
logger(LL_DEBUG, "Ctrl handshake done (ConnPort = %" PRIu64 ")\n", (uint64_t)conn_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -353,13 +351,13 @@ static int fdr_sync_handshake(fdr_client_t fdr)
|
||||
|
||||
device_error = idevice_connection_send(fdr->connection, HELLOCMD, len, &bytes);
|
||||
if (device_error != IDEVICE_E_SUCCESS || bytes != len) {
|
||||
error("ERROR: FDR unable to send Hello. Sent %u of %u bytes.\n", bytes, len);
|
||||
logger(LL_ERROR, "FDR unable to send Hello. Sent %u of %u bytes.\n", bytes, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ctrlprotoversion == 2) {
|
||||
if (fdr_receive_plist(fdr, &reply)) {
|
||||
error("ERROR: FDR did not get HelloConn reply.\n");
|
||||
logger(LL_ERROR, "FDR did not get HelloConn reply.\n");
|
||||
return -1;
|
||||
}
|
||||
char* identifier = NULL;
|
||||
@@ -382,13 +380,13 @@ static int fdr_sync_handshake(fdr_client_t fdr)
|
||||
if (identifier) {
|
||||
free(identifier);
|
||||
}
|
||||
error("ERROR: Did not receive HelloConn reply...\n");
|
||||
logger(LL_ERROR, "Did not receive HelloConn reply...\n");
|
||||
return -1;
|
||||
}
|
||||
free(cmd);
|
||||
|
||||
if (identifier) {
|
||||
debug("Got device identifier %s\n", identifier);
|
||||
logger(LL_DEBUG, "Got device identifier %s\n", identifier);
|
||||
free(identifier);
|
||||
}
|
||||
|
||||
@@ -398,12 +396,12 @@ static int fdr_sync_handshake(fdr_client_t fdr)
|
||||
bytes = 0;
|
||||
device_error = idevice_connection_receive(fdr->connection, buf, 10, &bytes);
|
||||
if (device_error != IDEVICE_E_SUCCESS) {
|
||||
error("ERROR: Could not receive reply to HelloConn command\n");
|
||||
logger(LL_ERROR, "Could not receive reply to HelloConn command\n");
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(buf, "HelloConn", 10) != 0) {
|
||||
buf[9] = '\0';
|
||||
error("ERROR: Did not receive HelloConn as reply, but %s\n", buf);
|
||||
logger(LL_ERROR, "Did not receive HelloConn as reply, but %s\n", buf);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -422,18 +420,18 @@ static int fdr_handle_sync_cmd(fdr_client_t fdr_ctrl)
|
||||
|
||||
device_error = idevice_connection_receive(fdr_ctrl->connection, buf, sizeof(buf), &bytes);
|
||||
if (device_error != IDEVICE_E_SUCCESS || bytes != 2) {
|
||||
error("ERROR: Unexpected data from FDR\n");
|
||||
logger(LL_ERROR, "Unexpected data from FDR\n");
|
||||
return -1;
|
||||
}
|
||||
/* Open a new connection and wait for messages on it */
|
||||
if (fdr_connect(fdr_ctrl->device, FDR_CONN, &fdr)) {
|
||||
error("ERROR: Failed to connect to FDR port\n");
|
||||
logger(LL_ERROR, "Failed to connect to FDR port\n");
|
||||
return -1;
|
||||
}
|
||||
debug("FDR connected in reply to sync message, starting command thread\n");
|
||||
logger(LL_DEBUG, "FDR connected in reply to sync message, starting command thread\n");
|
||||
res = thread_new(&fdr_thread, fdr_listener_thread, fdr);
|
||||
if(res) {
|
||||
error("ERROR: Failed to start FDR command thread\n");
|
||||
logger(LL_ERROR, "Failed to start FDR command thread\n");
|
||||
fdr_free(fdr);
|
||||
}
|
||||
return res;
|
||||
@@ -445,12 +443,12 @@ static int fdr_handle_plist_cmd(fdr_client_t fdr)
|
||||
plist_t dict;
|
||||
|
||||
if (fdr_receive_plist(fdr, &dict)) {
|
||||
error("ERROR: FDR %p could not receive plist command.\n", fdr);
|
||||
logger(LL_ERROR, "FDR %p could not receive plist command.\n", fdr);
|
||||
return -1;
|
||||
}
|
||||
plist_t node = plist_dict_get_item(dict, "Command");
|
||||
if (!node || (plist_get_node_type(node) != PLIST_STRING)) {
|
||||
error("ERROR: FDR %p Could not find Command in plist command\n", fdr);
|
||||
logger(LL_ERROR, "FDR %p Could not find Command in plist command\n", fdr);
|
||||
plist_free(dict);
|
||||
return -1;
|
||||
}
|
||||
@@ -459,7 +457,7 @@ static int fdr_handle_plist_cmd(fdr_client_t fdr)
|
||||
plist_free(dict);
|
||||
|
||||
if (!command) {
|
||||
info("FDR %p received empty plist command\n", fdr);
|
||||
logger(LL_INFO, "FDR %p received empty plist command\n", fdr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -469,12 +467,12 @@ static int fdr_handle_plist_cmd(fdr_client_t fdr)
|
||||
res = fdr_send_plist(fdr, dict);
|
||||
plist_free(dict);
|
||||
if (res) {
|
||||
error("ERROR: FDR %p could not send Ping command reply.\n", fdr);
|
||||
logger(LL_ERROR, "FDR %p could not send Ping command reply.\n", fdr);
|
||||
free(command);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error("WARNING: FDR %p received unknown plist command: %s\n", fdr, command);
|
||||
logger(LL_WARNING, "FDR %p received unknown plist command: %s\n", fdr, command);
|
||||
free(command);
|
||||
return -1;
|
||||
}
|
||||
@@ -495,17 +493,17 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
|
||||
|
||||
buf = malloc(bufsize);
|
||||
if (!buf) {
|
||||
error("ERROR: %s: malloc failed\n", __func__);
|
||||
logger(LL_ERROR, "%s: malloc failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
device_error = idevice_connection_receive(fdr->connection, buf, bufsize, &bytes);
|
||||
if (device_error != IDEVICE_E_SUCCESS) {
|
||||
free(buf);
|
||||
error("ERROR: FDR %p failed to read data for proxy command\n", fdr);
|
||||
logger(LL_ERROR, "FDR %p failed to read data for proxy command\n", fdr);
|
||||
return -1;
|
||||
}
|
||||
debug("Got proxy command with %u bytes\n", bytes);
|
||||
logger(LL_DEBUG, "Got proxy command with %u bytes\n", bytes);
|
||||
|
||||
/* Just return success here unconditionally because we don't know
|
||||
* anything else and we will eventually abort on failure anyway */
|
||||
@@ -513,13 +511,13 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
|
||||
device_error = idevice_connection_send(fdr->connection, (char *)&ack, sizeof(ack), &sent);
|
||||
if (device_error != IDEVICE_E_SUCCESS || sent != sizeof(ack)) {
|
||||
free(buf);
|
||||
error("ERROR: FDR %p unable to send ack. Sent %u of %u bytes.\n",
|
||||
logger(LL_ERROR, "FDR %p unable to send ack. Sent %u of %u bytes.\n",
|
||||
fdr, sent, (uint32_t)sizeof(ack));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bytes < 3) {
|
||||
debug("FDR %p proxy command data too short, retrying\n", fdr);
|
||||
logger(LL_DEBUG, "FDR %p proxy command data too short, retrying\n", fdr);
|
||||
return fdr_poll_and_handle_message(fdr);
|
||||
}
|
||||
|
||||
@@ -527,7 +525,7 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
|
||||
device_error = idevice_connection_send(fdr->connection, buf, bytes, &sent);
|
||||
if (device_error != IDEVICE_E_SUCCESS || sent != bytes) {
|
||||
free(buf);
|
||||
error("ERROR: FDR %p unable to send data. Sent %u of %u bytes.\n",
|
||||
logger(LL_ERROR, "FDR %p unable to send data. Sent %u of %u bytes.\n",
|
||||
fdr, sent, bytes);
|
||||
return -1;
|
||||
}
|
||||
@@ -539,7 +537,7 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
|
||||
port = be16toh(*p);
|
||||
buf[bytes - 2] = '\0';
|
||||
host = strdup(&buf[3]);
|
||||
debug("FDR %p Proxy connect request to %s:%u\n", fdr, host, port);
|
||||
logger(LL_DEBUG, "FDR %p Proxy connect request to %s:%u\n", fdr, host, port);
|
||||
}
|
||||
|
||||
if (!host || !buf[2]) {
|
||||
@@ -553,7 +551,7 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
|
||||
free(host);
|
||||
if (sockfd < 0) {
|
||||
free(buf);
|
||||
error("ERROR: Failed to connect socket: %s\n", strerror(errno));
|
||||
logger(LL_ERROR, "Failed to connect socket: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -567,16 +565,16 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
|
||||
if (device_error == IDEVICE_E_SUCCESS && !bytes)
|
||||
#endif
|
||||
{
|
||||
//debug("WARNING: Timeout waiting for proxy payload. %p\n", fdr);
|
||||
//logger(LL_DEBUG, "Timeout waiting for proxy payload. %p\n", fdr);
|
||||
}
|
||||
else if (device_error != IDEVICE_E_SUCCESS) {
|
||||
error("ERROR: FDR %p Unable to receive proxy payload (%d)\n", fdr, device_error);
|
||||
logger(LL_ERROR, "FDR %p Unable to receive proxy payload (%d)\n", fdr, device_error);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (bytes) {
|
||||
debug("FDR %p got payload of %u bytes, now trying to proxy it\n", fdr, bytes);
|
||||
debug("Sending %u bytes of data\n", bytes);
|
||||
logger(LL_DEBUG, "FDR %p got payload of %u bytes, now trying to proxy it\n", fdr, bytes);
|
||||
logger(LL_DEBUG, "Sending %u bytes of data\n", bytes);
|
||||
sent = 0;
|
||||
while (sent < bytes) {
|
||||
int s = socket_send(sockfd, buf + sent, bytes - sent);
|
||||
@@ -586,7 +584,7 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
|
||||
sent += s;
|
||||
}
|
||||
if (sent != bytes) {
|
||||
error("ERROR: Sending proxy payload failed: %s. Sent %u of %u bytes. \n", strerror(errno), sent, bytes);
|
||||
logger(LL_ERROR, "Sending proxy payload failed: %s. Sent %u of %u bytes. \n", strerror(errno), sent, bytes);
|
||||
socket_close(sockfd);
|
||||
res = -1;
|
||||
break;
|
||||
@@ -599,14 +597,14 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
|
||||
res = 1;
|
||||
break;
|
||||
} else if (bytes_ret < 0) {
|
||||
error("ERROR: FDR %p receiving proxy payload failed: %d (%s)\n",
|
||||
logger(LL_ERROR, "FDR %p receiving proxy payload failed: %d (%s)\n",
|
||||
fdr, bytes_ret, strerror(-bytes_ret));
|
||||
break;
|
||||
}
|
||||
|
||||
bytes = bytes_ret;
|
||||
if (bytes) {
|
||||
debug("FDR %p Received %u bytes reply data,%s sending to device\n",
|
||||
logger(LL_DEBUG, "FDR %p Received %u bytes reply data,%s sending to device\n",
|
||||
fdr, bytes, (bytes ? "" : " not"));
|
||||
|
||||
sent = 0;
|
||||
@@ -619,7 +617,7 @@ static int fdr_handle_proxy_cmd(fdr_client_t fdr)
|
||||
sent += s;
|
||||
}
|
||||
if (device_error != IDEVICE_E_SUCCESS || bytes != sent) {
|
||||
error("ERROR: FDR %p unable to send data (%d). Sent %u of %u bytes.\n", fdr, device_error, sent, bytes);
|
||||
logger(LL_ERROR, "FDR %p unable to send data (%d). Sent %u of %u bytes.\n", fdr, device_error, sent, bytes);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ static void fls_parse_elements(fls_file* fls)
|
||||
offset += cur->size;
|
||||
} while (offset < fls->size);
|
||||
if (offset != fls->size) {
|
||||
error("ERROR: %s: error parsing elements\n", __func__);
|
||||
logger(LL_ERROR, "%s: error parsing elements\n", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -136,22 +136,22 @@ int fls_update_sig_blob(fls_file* fls, const unsigned char* sigdata, unsigned in
|
||||
{
|
||||
/* FIXME: the code in this function is not big endian safe */
|
||||
if (!fls || !fls->num_elements) {
|
||||
error("ERROR: %s: no data\n", __func__);
|
||||
logger(LL_ERROR, "%s: no data\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (!fls->c_element) {
|
||||
error("ERROR: %s: no fls_0c_element in fls data\n", __func__);
|
||||
logger(LL_ERROR, "%s: no fls_0c_element in fls data\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t datasize = *(uint32_t*)(fls->c_element->data + 0x10);
|
||||
if (datasize != fls->c_element->data_size) {
|
||||
error("ERROR: %s: data size mismatch (0x%x != 0x%x)\n", __func__, datasize, fls->c_element->data_size);
|
||||
logger(LL_ERROR, "%s: data size mismatch (0x%x != 0x%x)\n", __func__, datasize, fls->c_element->data_size);
|
||||
return -1;
|
||||
}
|
||||
uint32_t sigoffset = *(uint32_t*)(fls->c_element->data + 0x14);
|
||||
if (sigoffset > datasize) {
|
||||
error("ERROR: %s: signature offset greater than data size (0x%x > 0x%x)\n", __func__, sigoffset, datasize);
|
||||
logger(LL_ERROR, "%s: signature offset greater than data size (0x%x > 0x%x)\n", __func__, sigoffset, datasize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ int fls_update_sig_blob(fls_file* fls, const unsigned char* sigdata, unsigned in
|
||||
uint32_t offset = 0;
|
||||
void* newdata = malloc(newsize);
|
||||
if (!newdata) {
|
||||
error("ERROR: %s: out of memory\n", __func__);
|
||||
logger(LL_ERROR, "%s: out of memory\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
uint32_t hdrsize = 0;
|
||||
@@ -243,11 +243,11 @@ int fls_insert_ticket(fls_file* fls, const unsigned char* data, unsigned int siz
|
||||
{
|
||||
/* FIXME: the code in this function is not big endian safe */
|
||||
if (!fls || !fls->num_elements) {
|
||||
error("ERROR: %s: no data\n", __func__);
|
||||
logger(LL_ERROR, "%s: no data\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (!fls->c_element) {
|
||||
error("ERROR: %s: no fls_0c_element in fls data\n", __func__);
|
||||
logger(LL_ERROR, "%s: no fls_0c_element in fls data\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ int fls_insert_ticket(fls_file* fls, const unsigned char* data, unsigned int siz
|
||||
uint32_t offset = 0;
|
||||
void* newdata = malloc(newsize);
|
||||
if (!newdata) {
|
||||
error("ERROR: %s: out of memory\n", __func__);
|
||||
logger(LL_ERROR, "%s: out of memory\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
uint32_t hdrsize = 0;
|
||||
|
||||
+5
-5
@@ -35,13 +35,13 @@ int ftab_parse(unsigned char *data, unsigned int data_size, ftab_t *ftab, uint32
|
||||
}
|
||||
|
||||
if (data_size < sizeof(struct ftab_header)) {
|
||||
error("ERROR: %s: Buffer too small for ftab data\n", __func__);
|
||||
logger(LL_ERROR, "%s: Buffer too small for ftab data\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ftab_header *hdr_ptr = (struct ftab_header*)data;
|
||||
if (be32toh(hdr_ptr->magic) != 'ftab') {
|
||||
error("ERROR: %s: Unexpected magic value 0x%08x\n", __func__, le32toh(hdr_ptr->magic));
|
||||
logger(LL_ERROR, "%s: Unexpected magic value 0x%08x\n", __func__, le32toh(hdr_ptr->magic));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -108,13 +108,13 @@ int ftab_add_entry(ftab_t ftab, uint32_t tag, unsigned char *data, unsigned int
|
||||
uint32_t new_index = ftab->header.num_entries;
|
||||
struct ftab_entry *new_entries = realloc(ftab->entries, sizeof(struct ftab_entry) * (ftab->header.num_entries + 1));
|
||||
if (!new_entries) {
|
||||
error("ERROR: %s: realloc failed!\n", __func__);
|
||||
logger(LL_ERROR, "%s: realloc failed!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
ftab->entries = new_entries;
|
||||
unsigned char **new_storage = realloc(ftab->storage, sizeof(unsigned char*) * (ftab->header.num_entries + 1));
|
||||
if (!new_storage) {
|
||||
error("ERROR: %s: realloc failed!\n", __func__);
|
||||
logger(LL_ERROR, "%s: realloc failed!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
ftab->storage = new_storage;
|
||||
@@ -151,7 +151,7 @@ int ftab_write(ftab_t ftab, unsigned char **data, unsigned int *data_size)
|
||||
|
||||
unsigned char *data_out = (unsigned char*)malloc(total_size);
|
||||
if (!data_out) {
|
||||
error("ERROR: %s: Out of memory?!\n", __func__);
|
||||
logger(LL_ERROR, "%s: Out of memory?!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
+344
-292
File diff suppressed because it is too large
Load Diff
@@ -46,6 +46,7 @@ extern "C" {
|
||||
#define FLAG_ALLOW_RESTORE_MODE (1 << 10)
|
||||
#define FLAG_NO_RESTORE (1 << 11)
|
||||
#define FLAG_IGNORE_ERRORS (1 << 12)
|
||||
#define FLAG_IN_PROGRESS (1 << 30)
|
||||
|
||||
#define RESTORE_VARIANT_ERASE_INSTALL "Erase Install (IPSW)"
|
||||
#define RESTORE_VARIANT_UPGRADE_INSTALL "Upgrade Install (IPSW)"
|
||||
@@ -83,9 +84,6 @@ void idevicerestore_set_flags(struct idevicerestore_client_t* client, int flags)
|
||||
void idevicerestore_set_ipsw(struct idevicerestore_client_t* client, const char* path);
|
||||
void idevicerestore_set_cache_path(struct idevicerestore_client_t* client, const char* path);
|
||||
void idevicerestore_set_progress_callback(struct idevicerestore_client_t* client, idevicerestore_progress_cb_t cbfunc, void* userdata);
|
||||
void idevicerestore_set_info_stream(FILE* strm);
|
||||
void idevicerestore_set_error_stream(FILE* strm);
|
||||
void idevicerestore_set_debug_stream(FILE* strm);
|
||||
|
||||
int idevicerestore_start(struct idevicerestore_client_t* client);
|
||||
const char* idevicerestore_get_error(void);
|
||||
|
||||
+39
-39
@@ -38,13 +38,13 @@ static img3_file* img3_parse_file(const unsigned char* data, unsigned int size)
|
||||
img3_element* element;
|
||||
img3_header* header = (img3_header*) data;
|
||||
if (header->signature != kImg3Container) {
|
||||
error("ERROR: Invalid IMG3 file\n");
|
||||
logger(LL_ERROR, "Invalid IMG3 file\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
img3_file* image = (img3_file*) malloc(sizeof(img3_file));
|
||||
if (image == NULL) {
|
||||
error("ERROR: Unable to allocate memory for IMG3 file\n");
|
||||
logger(LL_ERROR, "Unable to allocate memory for IMG3 file\n");
|
||||
return NULL;
|
||||
}
|
||||
memset(image, '\0', sizeof(img3_file));
|
||||
@@ -54,7 +54,7 @@ static img3_file* img3_parse_file(const unsigned char* data, unsigned int size)
|
||||
|
||||
image->header = (img3_header*) malloc(sizeof(img3_header));
|
||||
if (image->header == NULL) {
|
||||
error("ERROR: Unable to allocate memory for IMG3 header\n");
|
||||
logger(LL_ERROR, "Unable to allocate memory for IMG3 header\n");
|
||||
img3_free(image);
|
||||
return NULL;
|
||||
}
|
||||
@@ -68,129 +68,129 @@ static img3_file* img3_parse_file(const unsigned char* data, unsigned int size)
|
||||
case kTypeElement:
|
||||
element = img3_parse_element(&data[data_offset]);
|
||||
if (element == NULL) {
|
||||
error("ERROR: Unable to parse TYPE element\n");
|
||||
logger(LL_ERROR, "Unable to parse TYPE element\n");
|
||||
img3_free(image);
|
||||
return NULL;
|
||||
}
|
||||
image->elements[image->num_elements++] = element;
|
||||
debug("Parsed TYPE element\n");
|
||||
logger(LL_DEBUG, "Parsed TYPE element\n");
|
||||
break;
|
||||
|
||||
case kDataElement:
|
||||
element = img3_parse_element(&data[data_offset]);
|
||||
if (element == NULL) {
|
||||
error("ERROR: Unable to parse DATA element\n");
|
||||
logger(LL_ERROR, "Unable to parse DATA element\n");
|
||||
img3_free(image);
|
||||
return NULL;
|
||||
}
|
||||
image->elements[image->num_elements++] = element;
|
||||
debug("Parsed DATA element\n");
|
||||
logger(LL_DEBUG, "Parsed DATA element\n");
|
||||
break;
|
||||
|
||||
case kVersElement:
|
||||
element = img3_parse_element(&data[data_offset]);
|
||||
if (element == NULL) {
|
||||
error("ERROR: Unable to parse VERS element\n");
|
||||
logger(LL_ERROR, "Unable to parse VERS element\n");
|
||||
img3_free(image);
|
||||
return NULL;
|
||||
}
|
||||
image->elements[image->num_elements++] = element;
|
||||
debug("Parsed VERS element\n");
|
||||
logger(LL_DEBUG, "Parsed VERS element\n");
|
||||
break;
|
||||
|
||||
case kSepoElement:
|
||||
element = img3_parse_element(&data[data_offset]);
|
||||
if (element == NULL) {
|
||||
error("ERROR: Unable to parse SEPO element\n");
|
||||
logger(LL_ERROR, "Unable to parse SEPO element\n");
|
||||
img3_free(image);
|
||||
return NULL;
|
||||
}
|
||||
image->elements[image->num_elements++] = element;
|
||||
debug("Parsed SEPO element\n");
|
||||
logger(LL_DEBUG, "Parsed SEPO element\n");
|
||||
break;
|
||||
|
||||
case kBordElement:
|
||||
element = img3_parse_element(&data[data_offset]);
|
||||
if (element == NULL) {
|
||||
error("ERROR: Unable to parse BORD element\n");
|
||||
logger(LL_ERROR, "Unable to parse BORD element\n");
|
||||
img3_free(image);
|
||||
return NULL;
|
||||
}
|
||||
image->elements[image->num_elements++] = element;
|
||||
debug("Parsed BORD element\n");
|
||||
logger(LL_DEBUG, "Parsed BORD element\n");
|
||||
break;
|
||||
|
||||
case kChipElement:
|
||||
element = img3_parse_element(&data[data_offset]);
|
||||
if (element == NULL) {
|
||||
error("ERROR: Unable to parse CHIP element\n");
|
||||
logger(LL_ERROR, "Unable to parse CHIP element\n");
|
||||
img3_free(image);
|
||||
return NULL;
|
||||
}
|
||||
image->elements[image->num_elements++] = element;
|
||||
debug("Parsed CHIP element\n");
|
||||
logger(LL_DEBUG, "Parsed CHIP element\n");
|
||||
break;
|
||||
|
||||
case kKbagElement:
|
||||
element = img3_parse_element(&data[data_offset]);
|
||||
if (element == NULL) {
|
||||
error("ERROR: Unable to parse first KBAG element\n");
|
||||
logger(LL_ERROR, "Unable to parse first KBAG element\n");
|
||||
img3_free(image);
|
||||
return NULL;
|
||||
}
|
||||
image->elements[image->num_elements++] = element;
|
||||
debug("Parsed KBAG element\n");
|
||||
logger(LL_DEBUG, "Parsed KBAG element\n");
|
||||
break;
|
||||
|
||||
case kEcidElement:
|
||||
element = img3_parse_element(&data[data_offset]);
|
||||
if (element == NULL) {
|
||||
error("ERROR: Unable to parse ECID element\n");
|
||||
logger(LL_ERROR, "Unable to parse ECID element\n");
|
||||
img3_free(image);
|
||||
return NULL;
|
||||
}
|
||||
image->idx_ecid_element = image->num_elements;
|
||||
image->elements[image->num_elements++] = element;
|
||||
debug("Parsed ECID element\n");
|
||||
logger(LL_DEBUG, "Parsed ECID element\n");
|
||||
break;
|
||||
|
||||
case kShshElement:
|
||||
element = img3_parse_element(&data[data_offset]);
|
||||
if (element == NULL) {
|
||||
error("ERROR: Unable to parse SHSH element\n");
|
||||
logger(LL_ERROR, "Unable to parse SHSH element\n");
|
||||
img3_free(image);
|
||||
return NULL;
|
||||
}
|
||||
image->idx_shsh_element = image->num_elements;
|
||||
image->elements[image->num_elements++] = element;
|
||||
debug("Parsed SHSH element\n");
|
||||
logger(LL_DEBUG, "Parsed SHSH element\n");
|
||||
break;
|
||||
|
||||
case kCertElement:
|
||||
element = img3_parse_element(&data[data_offset]);
|
||||
if (element == NULL) {
|
||||
error("ERROR: Unable to parse CERT element\n");
|
||||
logger(LL_ERROR, "Unable to parse CERT element\n");
|
||||
img3_free(image);
|
||||
return NULL;
|
||||
}
|
||||
image->idx_cert_element = image->num_elements;
|
||||
image->elements[image->num_elements++] = element;
|
||||
debug("Parsed CERT element\n");
|
||||
logger(LL_DEBUG, "Parsed CERT element\n");
|
||||
break;
|
||||
|
||||
case kUnknElement:
|
||||
element = img3_parse_element(&data[data_offset]);
|
||||
if (element == NULL) {
|
||||
error("ERROR: Unable to parse UNKN element\n");
|
||||
logger(LL_ERROR, "Unable to parse UNKN element\n");
|
||||
img3_free(image);
|
||||
return NULL;
|
||||
}
|
||||
image->elements[image->num_elements++] = element;
|
||||
debug("Parsed UNKN element\n");
|
||||
logger(LL_DEBUG, "Parsed UNKN element\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
error("ERROR: Unknown IMG3 element type %08x\n", current->signature);
|
||||
logger(LL_ERROR, "Unknown IMG3 element type %08x\n", current->signature);
|
||||
img3_free(image);
|
||||
return NULL;
|
||||
}
|
||||
@@ -204,14 +204,14 @@ static img3_element* img3_parse_element(const unsigned char* data) {
|
||||
img3_element_header* element_header = (img3_element_header*) data;
|
||||
img3_element* element = (img3_element*) malloc(sizeof(img3_element));
|
||||
if (element == NULL) {
|
||||
error("ERROR: Unable to allocate memory for IMG3 element\n");
|
||||
logger(LL_ERROR, "Unable to allocate memory for IMG3 element\n");
|
||||
return NULL;
|
||||
}
|
||||
memset(element, '\0', sizeof(img3_element));
|
||||
|
||||
element->data = (unsigned char*) malloc(element_header->full_size);
|
||||
if (element->data == NULL) {
|
||||
error("ERROR: Unable to allocate memory for IMG3 element data\n");
|
||||
logger(LL_ERROR, "Unable to allocate memory for IMG3 element data\n");
|
||||
free(element);
|
||||
return NULL;
|
||||
}
|
||||
@@ -254,21 +254,21 @@ static int img3_replace_signature(img3_file* image, const unsigned char* signatu
|
||||
int offset = 0;
|
||||
img3_element* ecid = img3_parse_element(&signature[offset]);
|
||||
if (ecid == NULL || ecid->type != kEcidElement) {
|
||||
error("ERROR: Unable to find ECID element in signature\n");
|
||||
logger(LL_ERROR, "Unable to find ECID element in signature\n");
|
||||
return -1;
|
||||
}
|
||||
offset += ecid->header->full_size;
|
||||
|
||||
img3_element* shsh = img3_parse_element(&signature[offset]);
|
||||
if (shsh == NULL || shsh->type != kShshElement) {
|
||||
error("ERROR: Unable to find SHSH element in signature\n");
|
||||
logger(LL_ERROR, "Unable to find SHSH element in signature\n");
|
||||
return -1;
|
||||
}
|
||||
offset += shsh->header->full_size;
|
||||
|
||||
img3_element* cert = img3_parse_element(&signature[offset]);
|
||||
if (cert == NULL || cert->type != kCertElement) {
|
||||
error("ERROR: Unable to find CERT element in signature\n");
|
||||
logger(LL_ERROR, "Unable to find CERT element in signature\n");
|
||||
return -1;
|
||||
}
|
||||
offset += cert->header->full_size;
|
||||
@@ -364,11 +364,11 @@ static int img3_get_data(img3_file* image, unsigned char** pdata, unsigned int*
|
||||
size += image->elements[i]->header->full_size;
|
||||
}
|
||||
|
||||
info("reconstructed size: %d\n", size);
|
||||
logger(LL_INFO, "reconstructed size: %d\n", size);
|
||||
|
||||
unsigned char* data = (unsigned char*) malloc(size);
|
||||
if (data == NULL) {
|
||||
error("ERROR: Unable to allocate memory for IMG3 data\n");
|
||||
logger(LL_ERROR, "Unable to allocate memory for IMG3 data\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -390,7 +390,7 @@ static int img3_get_data(img3_file* image, unsigned char** pdata, unsigned int*
|
||||
}
|
||||
|
||||
if (offset != size) {
|
||||
error("ERROR: Incorrectly sized image data\n");
|
||||
logger(LL_ERROR, "Incorrectly sized image data\n");
|
||||
free(data);
|
||||
*pdata = 0;
|
||||
*psize = 0;
|
||||
@@ -412,31 +412,31 @@ int img3_stitch_component(const char* component_name, const unsigned char* compo
|
||||
return -1;
|
||||
}
|
||||
|
||||
info("Personalizing IMG3 component %s...\n", component_name);
|
||||
logger(LL_INFO, "Personalizing IMG3 component %s...\n", component_name);
|
||||
|
||||
/* parse current component as img3 */
|
||||
img3 = img3_parse_file(component_data, component_size);
|
||||
if (img3 == NULL) {
|
||||
error("ERROR: Unable to parse %s IMG3 file\n", component_name);
|
||||
logger(LL_ERROR, "Unable to parse %s IMG3 file\n", component_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((img3_element_header*)blob)->full_size != blob_size) {
|
||||
error("ERROR: Invalid blob passed for %s IMG3: The size %d embedded in the blob does not match the passed size of %d\n", component_name, ((img3_element_header*)blob)->full_size, blob_size);
|
||||
logger(LL_ERROR, "Invalid blob passed for %s IMG3: The size %d embedded in the blob does not match the passed size of %d\n", component_name, ((img3_element_header*)blob)->full_size, blob_size);
|
||||
img3_free(img3);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* personalize the component using the blob */
|
||||
if (img3_replace_signature(img3, blob) < 0) {
|
||||
error("ERROR: Unable to replace %s IMG3 signature\n", component_name);
|
||||
logger(LL_ERROR, "Unable to replace %s IMG3 signature\n", component_name);
|
||||
img3_free(img3);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get the img3 file as data */
|
||||
if (img3_get_data(img3, &outbuf, &outsize) < 0) {
|
||||
error("ERROR: Unable to reconstruct %s IMG3\n", component_name);
|
||||
logger(LL_ERROR, "Unable to reconstruct %s IMG3\n", component_name);
|
||||
img3_free(img3);
|
||||
return -1;
|
||||
}
|
||||
|
||||
+12
-12
@@ -204,7 +204,7 @@ static void asn1_write_element(unsigned char **p, unsigned int *length, unsigned
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
fprintf(stderr, "ERROR: %s: type %02x is not implemented\n", __func__, type);
|
||||
logger(LL_ERROR, "%s: type %02x is not implemented\n", __func__, type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -415,15 +415,15 @@ int img4_stitch_component(const char* component_name, const unsigned char* compo
|
||||
}
|
||||
|
||||
if (tss_response_get_ap_img4_ticket(tss_response, &blob, &blob_size) != 0) {
|
||||
error("ERROR: %s: Failed to get ApImg4Ticket from TSS response\n", __func__);
|
||||
logger(LL_ERROR, "%s: Failed to get ApImg4Ticket from TSS response\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
info("Personalizing IMG4 component %s...\n", component_name);
|
||||
logger(LL_INFO, "Personalizing IMG4 component %s...\n", component_name);
|
||||
/* first we need check if we have to change the tag for the given component */
|
||||
const void *tag = asn1_find_element(1, ASN1_IA5_STRING, component_data);
|
||||
if (tag) {
|
||||
debug("Tag found\n");
|
||||
logger(LL_DEBUG, "Tag found\n");
|
||||
if (strcmp(component_name, "RestoreKernelCache") == 0) {
|
||||
memcpy((void*)tag, "rkrn", 4);
|
||||
} else if (strcmp(component_name, "RestoreDeviceTree") == 0) {
|
||||
@@ -467,22 +467,22 @@ int img4_stitch_component(const char* component_name, const unsigned char* compo
|
||||
if (tbm_dict) {
|
||||
plist_t dt = plist_dict_get_item(tbm_dict, "ucon");
|
||||
if (!dt) {
|
||||
error("ERROR: %s: Missing ucon node in %s-TBM dictionary\n", __func__, component_name);
|
||||
logger(LL_ERROR, "%s: Missing ucon node in %s-TBM dictionary\n", __func__, component_name);
|
||||
return -1;
|
||||
}
|
||||
ucon_data = plist_get_data_ptr(dt, &ucon_size);
|
||||
if (!ucon_data) {
|
||||
error("ERROR: %s: Missing ucon data in %s-TBM dictionary\n", __func__, component_name);
|
||||
logger(LL_ERROR, "%s: Missing ucon data in %s-TBM dictionary\n", __func__, component_name);
|
||||
return -1;
|
||||
}
|
||||
dt = plist_dict_get_item(tbm_dict, "ucer");
|
||||
if (!dt) {
|
||||
error("ERROR: %s: Missing ucer data node in %s-TBM dictionary\n", __func__, component_name);
|
||||
logger(LL_ERROR, "%s: Missing ucer data node in %s-TBM dictionary\n", __func__, component_name);
|
||||
return -1;
|
||||
}
|
||||
ucer_data = plist_get_data_ptr(dt, &ucer_size);
|
||||
if (!ucer_data) {
|
||||
error("ERROR: %s: Missing ucer data in %s-TBM dictionary\n", __func__, component_name);
|
||||
logger(LL_ERROR, "%s: Missing ucer data in %s-TBM dictionary\n", __func__, component_name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -683,7 +683,7 @@ int img4_stitch_component(const char* component_name, const unsigned char* compo
|
||||
free(img4header);
|
||||
}
|
||||
free(additional_data);
|
||||
error("ERROR: out of memory when personalizing IMG4 component %s\n", component_name);
|
||||
logger(LL_ERROR, "out of memory when personalizing IMG4 component %s\n", component_name);
|
||||
return -1;
|
||||
}
|
||||
p = outbuf;
|
||||
@@ -825,7 +825,7 @@ static void _manifest_write_component(unsigned char **p, unsigned int *length, c
|
||||
tbmtag = "tbmr";
|
||||
}
|
||||
if (!tbmtag) {
|
||||
error("ERROR: Unexpected TMBDigests for comp '%s'\n", tag);
|
||||
logger(LL_ERROR, "Unexpected TMBDigests for comp '%s'\n", tag);
|
||||
} else {
|
||||
_manifest_write_key_value(&tmp, &tmp_len, tbmtag, ASN1_OCTET_STRING, (void*)data, datalen);
|
||||
}
|
||||
@@ -918,10 +918,10 @@ int img4_create_local_manifest(plist_t request, plist_t build_identity, plist_t*
|
||||
comp = _img4_get_component_tag(key);
|
||||
}
|
||||
if (!comp) {
|
||||
debug("DEBUG: %s: Unhandled component '%s'\n", __func__, key);
|
||||
logger(LL_DEBUG, "%s: Unhandled component '%s'\n", __func__, key);
|
||||
_manifest_write_component(&p, &length, key, val);
|
||||
} else {
|
||||
debug("DEBUG: found component %s (%s)\n", comp, key);
|
||||
logger(LL_DEBUG, "found component %s (%s)\n", comp, key);
|
||||
_manifest_write_component(&p, &length, comp, val);
|
||||
}
|
||||
}
|
||||
|
||||
+135
-107
@@ -69,7 +69,7 @@ int ipsw_print_info(const char* path)
|
||||
struct stat fst;
|
||||
|
||||
if (stat(path, &fst) != 0) {
|
||||
error("ERROR: '%s': %s\n", path, strerror(errno));
|
||||
logger(LL_ERROR, "'%s': %s\n", path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ int ipsw_print_info(const char* path)
|
||||
if (S_ISDIR(fst.st_mode)) {
|
||||
snprintf(thepath, sizeof(thepath), "%s/BuildManifest.plist", path);
|
||||
if (stat(thepath, &fst) != 0) {
|
||||
error("ERROR: '%s': %s\n", thepath, strerror(errno));
|
||||
logger(LL_ERROR, "'%s': %s\n", thepath, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
@@ -87,13 +87,13 @@ int ipsw_print_info(const char* path)
|
||||
|
||||
FILE* f = fopen(thepath, "r");
|
||||
if (!f) {
|
||||
error("ERROR: Can't open '%s': %s\n", thepath, strerror(errno));
|
||||
logger(LL_ERROR, "Can't open '%s': %s\n", thepath, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
uint32_t magic;
|
||||
if (fread(&magic, 1, 4, f) != 4) {
|
||||
fclose(f);
|
||||
fprintf(stderr, "Failed to read from '%s'\n", path);
|
||||
logger(LL_ERROR, "Failed to read from '%s'\n", path);
|
||||
return -1;
|
||||
}
|
||||
fclose(f);
|
||||
@@ -106,7 +106,7 @@ int ipsw_print_info(const char* path)
|
||||
unsigned int 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");
|
||||
logger(LL_ERROR, "Failed to extract BuildManifest.plist from IPSW!\n");
|
||||
return -1;
|
||||
}
|
||||
ipsw_close(ipsw);
|
||||
@@ -114,7 +114,7 @@ int ipsw_print_info(const char* path)
|
||||
} else {
|
||||
size_t rlen = 0;
|
||||
if (read_file(thepath, (void**)&plist_buf, &rlen) < 0) {
|
||||
error("ERROR: Failed to read BuildManifest.plist!\n");
|
||||
logger(LL_ERROR, "Failed to read BuildManifest.plist!\n");
|
||||
return -1;
|
||||
}
|
||||
plist_len = (uint32_t)rlen;
|
||||
@@ -302,13 +302,13 @@ ipsw_archive_t ipsw_open(const char* ipsw)
|
||||
int err = 0;
|
||||
ipsw_archive_t archive = (ipsw_archive_t)calloc(1, sizeof(struct ipsw_archive));
|
||||
if (archive == NULL) {
|
||||
error("ERROR: Out of memory\n");
|
||||
logger(LL_ERROR, "Out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct stat fst;
|
||||
if (stat(ipsw, &fst) != 0) {
|
||||
error("ERROR: ipsw_open %s: %s\n", ipsw, strerror(errno));
|
||||
logger(LL_ERROR, "ipsw_open %s: %s\n", ipsw, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
if (S_ISDIR(fst.st_mode)) {
|
||||
@@ -316,7 +316,7 @@ ipsw_archive_t ipsw_open(const char* ipsw)
|
||||
} else {
|
||||
struct zip *zip = zip_open(ipsw, 0, &err);
|
||||
if (zip == NULL) {
|
||||
error("ERROR: zip_open: %s: %d\n", ipsw, err);
|
||||
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw, err);
|
||||
free(archive);
|
||||
return NULL;
|
||||
}
|
||||
@@ -347,7 +347,7 @@ int ipsw_is_directory(const char* ipsw)
|
||||
int ipsw_get_file_size(ipsw_archive_t ipsw, const char* infile, uint64_t* size)
|
||||
{
|
||||
if (ipsw == NULL) {
|
||||
error("ERROR: Invalid archive\n");
|
||||
logger(LL_ERROR, "Invalid archive\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -355,12 +355,12 @@ int ipsw_get_file_size(ipsw_archive_t ipsw, const char* infile, uint64_t* size)
|
||||
int err = 0;
|
||||
struct zip *zip = zip_open(ipsw->path, 0, &err);
|
||||
if (zip == NULL) {
|
||||
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
|
||||
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
|
||||
return -1;
|
||||
}
|
||||
int zindex = zip_name_locate(zip, infile, 0);
|
||||
if (zindex < 0) {
|
||||
error("ERROR: zip_name_locate: %s\n", infile);
|
||||
logger(LL_ERROR, "zip_name_locate: %s\n", infile);
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
return -1;
|
||||
@@ -369,7 +369,7 @@ int ipsw_get_file_size(ipsw_archive_t ipsw, const char* infile, uint64_t* size)
|
||||
struct zip_stat zstat;
|
||||
zip_stat_init(&zstat);
|
||||
if (zip_stat_index(zip, zindex, 0, &zstat) != 0) {
|
||||
error("ERROR: zip_stat_index: %s\n", infile);
|
||||
logger(LL_ERROR, "zip_stat_index: %s\n", infile);
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
return -1;
|
||||
@@ -398,7 +398,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
|
||||
int ret = 0;
|
||||
|
||||
if (!ipsw || !infile || !outfile) {
|
||||
error("ERROR: Invalid argument\n");
|
||||
logger(LL_ERROR, "Invalid argument\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -408,7 +408,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
|
||||
int err = 0;
|
||||
struct zip *zip = zip_open(ipsw->path, 0, &err);
|
||||
if (zip == NULL) {
|
||||
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
|
||||
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
|
||||
if (zindex < 0) {
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
error("ERROR: zip_name_locate: %s\n", infile);
|
||||
logger(LL_ERROR, "zip_name_locate: %s\n", infile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -425,7 +425,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
|
||||
if (zip_stat_index(zip, zindex, 0, &zstat) != 0) {
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
error("ERROR: zip_stat_index: %s\n", infile);
|
||||
logger(LL_ERROR, "zip_stat_index: %s\n", infile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
|
||||
if (buffer == NULL) {
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
error("ERROR: Unable to allocate memory\n");
|
||||
logger(LL_ERROR, "Unable to allocate memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -441,7 +441,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
|
||||
if (zfile == NULL) {
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
error("ERROR: zip_fopen_index: %s\n", infile);
|
||||
logger(LL_ERROR, "zip_fopen_index: %s\n", infile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -450,13 +450,15 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
|
||||
zip_fclose(zfile);
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
error("ERROR: Unable to open output file: %s\n", outfile);
|
||||
logger(LL_ERROR, "Unable to open output file: %s\n", outfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (print_progress) {
|
||||
register_progress('IPSW', "Extracting");
|
||||
}
|
||||
uint64_t i, bytes = 0;
|
||||
int count, size = BUFSIZE;
|
||||
double progress;
|
||||
for(i = zstat.size; i > 0; i -= count) {
|
||||
if (cancel_flag) {
|
||||
break;
|
||||
@@ -468,23 +470,26 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
|
||||
int zep = 0;
|
||||
int sep = 0;
|
||||
zip_file_error_get(zfile, &zep, &sep);
|
||||
error("ERROR: zip_fread: %s %d %d\n", infile, zep, sep);
|
||||
logger(LL_ERROR, "zip_fread: %s %d %d\n", infile, zep, sep);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (fwrite(buffer, 1, count, fd) != count) {
|
||||
error("ERROR: Writing to '%s' failed: %s\n", outfile, strerror(errno));
|
||||
logger(LL_ERROR, "Writing to '%s' failed: %s\n", outfile, strerror(errno));
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
bytes += size;
|
||||
if (print_progress) {
|
||||
progress = ((double)bytes / (double)zstat.size) * 100.0;
|
||||
print_progress_bar(progress);
|
||||
double progress = ((double)bytes / (double)zstat.size);
|
||||
set_progress('IPSW', progress);
|
||||
}
|
||||
}
|
||||
free(buffer);
|
||||
if (print_progress) {
|
||||
finalize_progress('IPSW');
|
||||
}
|
||||
fclose(fd);
|
||||
zip_fclose(zfile);
|
||||
zip_unchange_all(zip);
|
||||
@@ -498,7 +503,7 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
|
||||
goto leave;
|
||||
}
|
||||
if (!realpath(filepath, actual_filepath)) {
|
||||
error("ERROR: realpath failed on %s: %s\n", filepath, strerror(errno));
|
||||
logger(LL_ERROR, "realpath failed on %s: %s\n", filepath, strerror(errno));
|
||||
ret = -1;
|
||||
goto leave;
|
||||
} else {
|
||||
@@ -512,21 +517,21 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
|
||||
}
|
||||
FILE *fi = fopen(actual_filepath, "rb");
|
||||
if (!fi) {
|
||||
error("ERROR: fopen: %s: %s\n", actual_filepath, strerror(errno));
|
||||
logger(LL_ERROR, "fopen: %s: %s\n", actual_filepath, strerror(errno));
|
||||
ret = -1;
|
||||
goto leave;
|
||||
}
|
||||
struct stat fst;
|
||||
if (fstat(fileno(fi), &fst) != 0) {
|
||||
fclose(fi);
|
||||
error("ERROR: fstat: %s: %s\n", actual_filepath, strerror(errno));
|
||||
logger(LL_ERROR, "fstat: %s: %s\n", actual_filepath, strerror(errno));
|
||||
ret = -1;
|
||||
goto leave;
|
||||
}
|
||||
FILE *fo = fopen(actual_outfile, "wb");
|
||||
if (!fo) {
|
||||
fclose(fi);
|
||||
error("ERROR: fopen: %s: %s\n", actual_outfile, strerror(errno));
|
||||
logger(LL_ERROR, "fopen: %s: %s\n", actual_outfile, strerror(errno));
|
||||
ret = -1;
|
||||
goto leave;
|
||||
}
|
||||
@@ -534,34 +539,39 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile,
|
||||
if (buffer == NULL) {
|
||||
fclose(fi);
|
||||
fclose(fo);
|
||||
error("ERROR: Unable to allocate memory\n");
|
||||
logger(LL_ERROR, "Unable to allocate memory\n");
|
||||
ret = -1;
|
||||
goto leave;;
|
||||
}
|
||||
|
||||
if (print_progress) {
|
||||
register_progress('IPSW', "Extracting");
|
||||
}
|
||||
uint64_t bytes = 0;
|
||||
double progress;
|
||||
while (!feof(fi)) {
|
||||
if (cancel_flag) {
|
||||
break;
|
||||
}
|
||||
ssize_t r = fread(buffer, 1, BUFSIZE, fi);
|
||||
if (r < 0) {
|
||||
error("ERROR: fread failed: %s\n", strerror(errno));
|
||||
logger(LL_ERROR, "fread failed: %s\n", strerror(errno));
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (fwrite(buffer, 1, r, fo) != r) {
|
||||
error("ERROR: Writing to '%s' failed: %s\n", actual_outfile, strerror(errno));
|
||||
logger(LL_ERROR, "Writing to '%s' failed: %s\n", actual_outfile, strerror(errno));
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
bytes += r;
|
||||
if (print_progress) {
|
||||
progress = ((double)bytes / (double)fst.st_size) * 100.0;
|
||||
print_progress_bar(progress);
|
||||
double progress = ((double)bytes / (double)fst.st_size);
|
||||
set_progress('IPSW', progress);
|
||||
}
|
||||
}
|
||||
if (print_progress) {
|
||||
finalize_progress('IPSW');
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
fclose(fi);
|
||||
@@ -592,7 +602,7 @@ int ipsw_file_exists(ipsw_archive_t ipsw, const char* infile)
|
||||
int err = 0;
|
||||
struct zip *zip = zip_open(ipsw->path, 0, &err);
|
||||
if (zip == NULL) {
|
||||
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
|
||||
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
|
||||
return 0;
|
||||
}
|
||||
int zindex = zip_name_locate(zip, infile, 0);
|
||||
@@ -618,7 +628,7 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
|
||||
size_t size = 0;
|
||||
unsigned char* buffer = NULL;
|
||||
if (ipsw == NULL) {
|
||||
error("ERROR: Invalid archive\n");
|
||||
logger(LL_ERROR, "Invalid archive\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -626,7 +636,7 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
|
||||
int err = 0;
|
||||
struct zip *zip = zip_open(ipsw->path, 0, &err);
|
||||
if (zip == NULL) {
|
||||
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
|
||||
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -634,7 +644,7 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
|
||||
if (zindex < 0) {
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
debug("NOTE: zip_name_locate: '%s' not found in archive.\n", infile);
|
||||
logger(LL_DEBUG, "zip_name_locate: '%s' not found in archive.\n", infile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -643,7 +653,7 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
|
||||
if (zip_stat_index(zip, zindex, 0, &zstat) != 0) {
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
error("ERROR: zip_stat_index: %s\n", infile);
|
||||
logger(LL_ERROR, "zip_stat_index: %s\n", infile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -651,14 +661,14 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
|
||||
if (zfile == NULL) {
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
error("ERROR: zip_fopen_index: %s\n", infile);
|
||||
logger(LL_ERROR, "zip_fopen_index: %s\n", infile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size = zstat.size;
|
||||
buffer = (unsigned char*) malloc(size+1);
|
||||
if (buffer == NULL) {
|
||||
error("ERROR: Out of memory\n");
|
||||
logger(LL_ERROR, "Out of memory\n");
|
||||
zip_fclose(zfile);
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
@@ -673,11 +683,11 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
|
||||
int zep = 0;
|
||||
int sep = 0;
|
||||
zip_file_error_get(zfile, &zep, &sep);
|
||||
error("ERROR: zip_fread: %s %d %d\n", infile, zep, sep);
|
||||
logger(LL_ERROR, "zip_fread: %s %d %d\n", infile, zep, sep);
|
||||
free(buffer);
|
||||
return -1;
|
||||
} else if (zr != size) {
|
||||
error("ERROR: zip_fread: %s got only %lld of %zu\n", infile, zr, size);
|
||||
logger(LL_ERROR, "zip_fread: %s got only %lld of %zu\n", infile, zr, size);
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
@@ -691,14 +701,14 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
|
||||
#else
|
||||
if (lstat(filepath, &fst) != 0) {
|
||||
#endif
|
||||
error("ERROR: %s: stat failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
logger(LL_ERROR, "%s: stat failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
free(filepath);
|
||||
return -1;
|
||||
}
|
||||
size = fst.st_size;
|
||||
buffer = (unsigned char*)malloc(size+1);
|
||||
if (buffer == NULL) {
|
||||
error("ERROR: Out of memory\n");
|
||||
logger(LL_ERROR, "Out of memory\n");
|
||||
free(filepath);
|
||||
return -1;
|
||||
}
|
||||
@@ -706,7 +716,7 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
|
||||
#ifndef WIN32
|
||||
if (S_ISLNK(fst.st_mode)) {
|
||||
if (readlink(filepath, (char*)buffer, size) < 0) {
|
||||
error("ERROR: %s: readlink failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
logger(LL_ERROR, "%s: readlink failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
free(filepath);
|
||||
free(buffer);
|
||||
return -1;
|
||||
@@ -715,14 +725,14 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha
|
||||
#endif
|
||||
FILE *f = fopen(filepath, "rb");
|
||||
if (!f) {
|
||||
error("ERROR: %s: fopen failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
logger(LL_ERROR, "%s: fopen failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
free(filepath);
|
||||
free(buffer);
|
||||
return -2;
|
||||
}
|
||||
if (fread(buffer, 1, size, f) != size) {
|
||||
fclose(f);
|
||||
error("ERROR: %s: fread failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
logger(LL_ERROR, "%s: fread failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
free(filepath);
|
||||
free(buffer);
|
||||
return -1;
|
||||
@@ -748,7 +758,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
|
||||
size_t total_size = 0;
|
||||
|
||||
if (ipsw == NULL) {
|
||||
error("ERROR: Invalid archive\n");
|
||||
logger(LL_ERROR, "Invalid archive\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -756,7 +766,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
|
||||
int err = 0;
|
||||
struct zip *zip = zip_open(ipsw->path, 0, &err);
|
||||
if (zip == NULL) {
|
||||
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
|
||||
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -764,7 +774,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
|
||||
if (zindex < 0) {
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
debug("NOTE: zip_name_locate: '%s' not found in archive.\n", infile);
|
||||
logger(LL_DEBUG, "zip_name_locate: '%s' not found in archive.\n", infile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -773,7 +783,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
|
||||
if (zip_stat_index(zip, zindex, 0, &zstat) != 0) {
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
error("ERROR: zip_stat_index: %s\n", infile);
|
||||
logger(LL_ERROR, "zip_stat_index: %s\n", infile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -781,7 +791,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
|
||||
if (zfile == NULL) {
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
error("ERROR: zip_fopen_index: %s\n", infile);
|
||||
logger(LL_ERROR, "zip_fopen_index: %s\n", infile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -791,7 +801,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
|
||||
zip_fclose(zfile);
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
error("ERROR: Out of memory\n");
|
||||
logger(LL_ERROR, "Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -800,14 +810,14 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
|
||||
if (size > blocksize) size = blocksize;
|
||||
zip_int64_t zr = zip_fread(zfile, buffer, size);
|
||||
if (zr < 0) {
|
||||
error("ERROR: %s: zip_fread: %s\n", __func__, infile);
|
||||
logger(LL_ERROR, "%s: zip_fread: %s\n", __func__, infile);
|
||||
break;
|
||||
} else if (zr == 0) {
|
||||
// EOF
|
||||
break;
|
||||
}
|
||||
if (send_callback(ctx, buffer, zr, done, total_size) < 0) {
|
||||
error("ERROR: %s: send failed\n", __func__);
|
||||
logger(LL_ERROR, "%s: send failed\n", __func__);
|
||||
break;
|
||||
}
|
||||
done += zr;
|
||||
@@ -824,14 +834,14 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
|
||||
#else
|
||||
if (lstat(filepath, &fst) != 0) {
|
||||
#endif
|
||||
error("ERROR: %s: stat failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
logger(LL_ERROR, "%s: stat failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
free(filepath);
|
||||
return -1;
|
||||
}
|
||||
total_size = fst.st_size;
|
||||
buffer = (unsigned char*)malloc(blocksize);
|
||||
if (buffer == NULL) {
|
||||
error("ERROR: Out of memory\n");
|
||||
logger(LL_ERROR, "Out of memory\n");
|
||||
free(filepath);
|
||||
return -1;
|
||||
}
|
||||
@@ -840,7 +850,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
|
||||
if (S_ISLNK(fst.st_mode)) {
|
||||
ssize_t rl = readlink(filepath, (char*)buffer, (total_size > blocksize) ? blocksize : total_size);
|
||||
if (rl < 0) {
|
||||
error("ERROR: %s: readlink failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
logger(LL_ERROR, "%s: readlink failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
free(filepath);
|
||||
free(buffer);
|
||||
return -1;
|
||||
@@ -850,7 +860,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
|
||||
#endif
|
||||
FILE *f = fopen(filepath, "rb");
|
||||
if (!f) {
|
||||
error("ERROR: %s: fopen failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
logger(LL_ERROR, "%s: fopen failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
free(filepath);
|
||||
free(buffer);
|
||||
return -2;
|
||||
@@ -861,11 +871,11 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
|
||||
if (size > blocksize) size = blocksize;
|
||||
size_t fr = fread(buffer, 1, size, f);
|
||||
if (fr != size) {
|
||||
error("ERROR: %s: fread failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
logger(LL_ERROR, "%s: fread failed for %s: %s\n", __func__, filepath, strerror(errno));
|
||||
break;
|
||||
}
|
||||
if (send_callback(ctx, buffer, fr, done, total_size) < 0) {
|
||||
error("ERROR: %s: send failed\n", __func__);
|
||||
logger(LL_ERROR, "%s: send failed\n", __func__);
|
||||
break;
|
||||
}
|
||||
done += fr;
|
||||
@@ -879,7 +889,7 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip
|
||||
}
|
||||
|
||||
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);
|
||||
logger(LL_ERROR, "%s: Sending file data for %s failed (sent %" PRIu64 "/%" PRIu64 ")\n", __func__, infile, (uint64_t)done, (uint64_t)total_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -941,7 +951,7 @@ static int ipsw_list_contents_recurse(ipsw_archive_t ipsw, const char *path, ips
|
||||
DIR *dirp = opendir(base);
|
||||
|
||||
if (!dirp) {
|
||||
error("ERROR: failed to open directory %s\n", base);
|
||||
logger(LL_ERROR, "failed to open directory %s\n", base);
|
||||
free(base);
|
||||
return -1;
|
||||
}
|
||||
@@ -968,7 +978,7 @@ static int ipsw_list_contents_recurse(ipsw_archive_t ipsw, const char *path, ips
|
||||
ret = lstat(fpath, &st);
|
||||
#endif
|
||||
if (ret != 0) {
|
||||
error("ERROR: %s: stat failed for %s: %s\n", __func__, fpath, strerror(errno));
|
||||
logger(LL_ERROR, "%s: stat failed for %s: %s\n", __func__, fpath, strerror(errno));
|
||||
free(fpath);
|
||||
free(subpath);
|
||||
break;
|
||||
@@ -993,7 +1003,7 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx)
|
||||
int ret = 0;
|
||||
|
||||
if (ipsw == NULL) {
|
||||
error("ERROR: Invalid IPSW archive\n");
|
||||
logger(LL_ERROR, "Invalid IPSW archive\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1001,13 +1011,13 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx)
|
||||
int err = 0;
|
||||
struct zip *zip = zip_open(ipsw->path, 0, &err);
|
||||
if (zip == NULL) {
|
||||
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
|
||||
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int64_t entries = zip_get_num_entries(zip, 0);
|
||||
if (entries < 0) {
|
||||
error("ERROR: zip_get_num_entries failed\n");
|
||||
logger(LL_ERROR, "zip_get_num_entries failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1016,7 +1026,7 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx)
|
||||
|
||||
zip_stat_init(&stat);
|
||||
if (zip_stat_index(zip, index, 0, &stat) < 0) {
|
||||
error("ERROR: zip_stat_index failed for %s\n", stat.name);
|
||||
logger(LL_ERROR, "zip_stat_index failed for %s\n", stat.name);
|
||||
ret = -1;
|
||||
continue;
|
||||
}
|
||||
@@ -1024,12 +1034,12 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx)
|
||||
uint8_t opsys;
|
||||
uint32_t attributes;
|
||||
if (zip_file_get_external_attributes(zip, index, 0, &opsys, &attributes) < 0) {
|
||||
error("ERROR: zip_file_get_external_attributes failed for %s\n", stat.name);
|
||||
logger(LL_ERROR, "zip_file_get_external_attributes failed for %s\n", stat.name);
|
||||
ret = -1;
|
||||
continue;
|
||||
}
|
||||
if (opsys != ZIP_OPSYS_UNIX) {
|
||||
error("ERROR: File %s does not have UNIX attributes\n", stat.name);
|
||||
logger(LL_ERROR, "File %s does not have UNIX attributes\n", stat.name);
|
||||
ret = -1;
|
||||
continue;
|
||||
}
|
||||
@@ -1079,32 +1089,32 @@ int ipsw_get_signed_firmwares(const char* product, plist_t* firmwares)
|
||||
snprintf(url, sizeof(url), "https://api.ipsw.me/v4/device/%s", product);
|
||||
|
||||
if (download_to_buffer(url, &jdata, &jsize) < 0) {
|
||||
error("ERROR: Download from %s failed.\n", url);
|
||||
logger(LL_ERROR, "Download from %s failed.\n", url);
|
||||
return -1;
|
||||
}
|
||||
plist_from_json(jdata, jsize, &dict);
|
||||
free(jdata);
|
||||
if (!dict || plist_get_node_type(dict) != PLIST_DICT) {
|
||||
error("ERROR: Failed to parse json data.\n");
|
||||
logger(LL_ERROR, "Failed to parse json data.\n");
|
||||
plist_free(dict);
|
||||
return -1;
|
||||
}
|
||||
|
||||
node = plist_dict_get_item(dict, "identifier");
|
||||
if (!node || plist_get_node_type(node) != PLIST_STRING) {
|
||||
error("ERROR: Unexpected json data returned - missing 'identifier'\n");
|
||||
logger(LL_ERROR, "Unexpected json data returned - missing 'identifier'\n");
|
||||
plist_free(dict);
|
||||
return -1;
|
||||
}
|
||||
product_type = plist_get_string_ptr(node, NULL);
|
||||
if (!product_type || strcmp(product_type, product) != 0) {
|
||||
error("ERROR: Unexpected json data returned - failed to read identifier\n");
|
||||
logger(LL_ERROR, "Unexpected json data returned - failed to read identifier\n");
|
||||
plist_free(dict);
|
||||
return -1;
|
||||
}
|
||||
fws = plist_dict_get_item(dict, "firmwares");
|
||||
if (!fws || plist_get_node_type(fws) != PLIST_ARRAY) {
|
||||
error("ERROR: Unexpected json data returned - missing 'firmwares'\n");
|
||||
logger(LL_ERROR, "Unexpected json data returned - missing 'firmwares'\n");
|
||||
plist_free(dict);
|
||||
return -1;
|
||||
}
|
||||
@@ -1136,14 +1146,14 @@ int ipsw_get_latest_fw(plist_t version_data, const char* product, char** fwurl,
|
||||
|
||||
plist_t n1 = plist_dict_get_item(version_data, "MobileDeviceSoftwareVersionsByVersion");
|
||||
if (!n1) {
|
||||
error("%s: ERROR: Can't find MobileDeviceSoftwareVersionsByVersion dict in version data\n", __func__);
|
||||
logger(LL_ERROR, "%s: ERROR: Can't find MobileDeviceSoftwareVersionsByVersion dict in version data\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
plist_dict_iter iter = NULL;
|
||||
plist_dict_new_iter(n1, &iter);
|
||||
if (!iter) {
|
||||
error("%s: ERROR: Can't get dict iter\n", __func__);
|
||||
logger(LL_ERROR, "%s: ERROR: Can't get dict iter\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
char* key = NULL;
|
||||
@@ -1164,7 +1174,7 @@ int ipsw_get_latest_fw(plist_t version_data, const char* product, char** fwurl,
|
||||
free(iter);
|
||||
|
||||
if (major == 0) {
|
||||
error("%s: ERROR: Can't find major version?!\n", __func__);
|
||||
logger(LL_ERROR, "%s: ERROR: Can't find major version?!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1172,13 +1182,13 @@ int ipsw_get_latest_fw(plist_t version_data, const char* product, char** fwurl,
|
||||
snprintf(majstr, sizeof(majstr), "%"PRIu64, (uint64_t)major);
|
||||
n1 = plist_access_path(version_data, 7, "MobileDeviceSoftwareVersionsByVersion", majstr, "MobileDeviceSoftwareVersions", product, "Unknown", "Universal", "Restore");
|
||||
if (!n1) {
|
||||
error("%s: ERROR: Can't get Unknown/Universal/Restore node?!\n", __func__);
|
||||
logger(LL_ERROR, "%s: ERROR: Can't get Unknown/Universal/Restore node?!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
plist_t n2 = plist_dict_get_item(n1, "BuildVersion");
|
||||
if (!n2 || (plist_get_node_type(n2) != PLIST_STRING)) {
|
||||
error("%s: ERROR: Can't get build version node?!\n", __func__);
|
||||
logger(LL_ERROR, "%s: ERROR: Can't get build version node?!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1187,7 +1197,7 @@ int ipsw_get_latest_fw(plist_t version_data, const char* product, char** fwurl,
|
||||
|
||||
n1 = plist_access_path(version_data, 5, "MobileDeviceSoftwareVersionsByVersion", majstr, "MobileDeviceSoftwareVersions", product, strval);
|
||||
if (!n1) {
|
||||
error("%s: ERROR: Can't get MobileDeviceSoftwareVersions/%s node?!\n", __func__, strval);
|
||||
logger(LL_ERROR, "%s: ERROR: Can't get MobileDeviceSoftwareVersions/%s node?!\n", __func__, strval);
|
||||
free(strval);
|
||||
return -1;
|
||||
}
|
||||
@@ -1203,7 +1213,7 @@ int ipsw_get_latest_fw(plist_t version_data, const char* product, char** fwurl,
|
||||
free(strval);
|
||||
strval = NULL;
|
||||
if (!n1 || (plist_dict_get_size(n1) == 0)) {
|
||||
error("%s: ERROR: Can't get MobileDeviceSoftwareVersions/%s dict\n", __func__, product);
|
||||
logger(LL_ERROR, "%s: ERROR: Can't get MobileDeviceSoftwareVersions/%s dict\n", __func__, product);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1221,7 +1231,7 @@ int ipsw_get_latest_fw(plist_t version_data, const char* product, char** fwurl,
|
||||
|
||||
n2 = plist_access_path(n1, 2, "Restore", "FirmwareURL");
|
||||
if (!n2 || (plist_get_node_type(n2) != PLIST_STRING)) {
|
||||
error("%s: ERROR: Can't get FirmwareURL node\n", __func__);
|
||||
logger(LL_ERROR, "%s: ERROR: Can't get FirmwareURL node\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1254,13 +1264,23 @@ static int sha1_verify_fp(FILE* f, unsigned char* expected_sha1)
|
||||
{
|
||||
unsigned char tsha1[20];
|
||||
char buf[8192];
|
||||
size_t total = 0;
|
||||
struct stat fst;
|
||||
int lastprog = 0;
|
||||
if (!f) return 0;
|
||||
sha1_context sha1ctx;
|
||||
sha1_init(&sha1ctx);
|
||||
rewind(f);
|
||||
fstat(fileno(f), &fst);
|
||||
while (!feof(f)) {
|
||||
size_t sz = fread(buf, 1, 8192, f);
|
||||
sha1_update(&sha1ctx, buf, sz);
|
||||
total += sz;
|
||||
double p = (double)total / (double)fst.st_size;
|
||||
if ((int)(p*100) > lastprog) {
|
||||
set_progress('SHA1', p);
|
||||
lastprog = (int)(p*100);
|
||||
}
|
||||
}
|
||||
sha1_final(&sha1ctx, tsha1);
|
||||
return (memcmp(expected_sha1, tsha1, 20) == 0) ? 1 : 0;
|
||||
@@ -1270,7 +1290,7 @@ int ipsw_download_fw(const char *fwurl, unsigned char* isha1, const char* todir,
|
||||
{
|
||||
char* fwfn = strrchr(fwurl, '/');
|
||||
if (!fwfn) {
|
||||
error("ERROR: can't get local filename for firmware ipsw\n");
|
||||
logger(LL_ERROR, "can't get local filename for firmware ipsw\n");
|
||||
return -2;
|
||||
}
|
||||
fwfn++;
|
||||
@@ -1288,7 +1308,7 @@ int ipsw_download_fw(const char *fwurl, unsigned char* isha1, const char* todir,
|
||||
lock_info_t lockinfo;
|
||||
|
||||
if (lock_file(fwlock, &lockinfo) != 0) {
|
||||
error("WARNING: Could not lock file '%s'\n", fwlock);
|
||||
logger(LL_WARNING, "Could not lock file '%s'\n", fwlock);
|
||||
}
|
||||
|
||||
int need_dl = 0;
|
||||
@@ -1296,13 +1316,15 @@ int ipsw_download_fw(const char *fwurl, unsigned char* isha1, const char* todir,
|
||||
FILE* f = fopen(fwlfn, "rb");
|
||||
if (f) {
|
||||
if (memcmp(zsha1, isha1, 20) != 0) {
|
||||
info("Verifying '%s'...\n", fwlfn);
|
||||
logger(LL_INFO, "Verifying '%s'...\n", fwlfn);
|
||||
register_progress('SHA1', "Verifying");
|
||||
if (sha1_verify_fp(f, isha1)) {
|
||||
info("Checksum matches.\n");
|
||||
logger(LL_INFO, "Checksum matches.\n");
|
||||
} else {
|
||||
info("Checksum does not match.\n");
|
||||
logger(LL_INFO, "Checksum does not match.\n");
|
||||
need_dl = 1;
|
||||
}
|
||||
finalize_progress('SHA1');
|
||||
}
|
||||
fclose(f);
|
||||
} else {
|
||||
@@ -1312,29 +1334,35 @@ int ipsw_download_fw(const char *fwurl, unsigned char* isha1, const char* todir,
|
||||
int res = 0;
|
||||
if (need_dl) {
|
||||
if (strncmp(fwurl, "protected:", 10) == 0) {
|
||||
error("ERROR: Can't download '%s' because it needs a purchase.\n", fwfn);
|
||||
logger(LL_ERROR, "Can't download '%s' because it needs a purchase.\n", fwfn);
|
||||
res = -3;
|
||||
} else {
|
||||
remove(fwlfn);
|
||||
info("Downloading firmware (%s)\n", fwurl);
|
||||
logger(LL_INFO, "Downloading firmware (%s)\n", fwurl);
|
||||
download_to_file(fwurl, fwlfn, 1);
|
||||
if (global_quit_flag > 0) {
|
||||
logger(LL_NOTICE, "Download aborted by user\n");
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(isha1, zsha1, 20) != 0) {
|
||||
info("\nVerifying '%s'...\n", fwlfn);
|
||||
logger(LL_INFO, "Verifying '%s'...\n", fwlfn);
|
||||
FILE* f = fopen(fwlfn, "rb");
|
||||
if (f) {
|
||||
register_progress('SHA1', "Verifying");
|
||||
if (sha1_verify_fp(f, isha1)) {
|
||||
info("Checksum matches.\n");
|
||||
logger(LL_INFO, "Checksum matches.\n");
|
||||
} else {
|
||||
error("ERROR: File download failed (checksum mismatch).\n");
|
||||
logger(LL_ERROR, "File download failed (checksum mismatch).\n");
|
||||
res = -4;
|
||||
}
|
||||
finalize_progress('SHA1');
|
||||
fclose(f);
|
||||
|
||||
// make sure to remove invalid files
|
||||
if (res < 0)
|
||||
remove(fwlfn);
|
||||
} else {
|
||||
error("ERROR: Can't open '%s' for checksum verification\n", fwlfn);
|
||||
logger(LL_ERROR, "Can't open '%s' for checksum verification\n", fwlfn);
|
||||
res = -5;
|
||||
}
|
||||
}
|
||||
@@ -1345,7 +1373,7 @@ int ipsw_download_fw(const char *fwurl, unsigned char* isha1, const char* todir,
|
||||
}
|
||||
|
||||
if (unlock_file(&lockinfo) != 0) {
|
||||
error("WARNING: Could not unlock file '%s'\n", fwlock);
|
||||
logger(LL_WARNING, "Could not unlock file '%s'\n", fwlock);
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -1359,17 +1387,17 @@ int ipsw_download_latest_fw(plist_t version_data, const char* product, const cha
|
||||
*ipswfile = NULL;
|
||||
|
||||
if ((ipsw_get_latest_fw(version_data, product, &fwurl, isha1) < 0) || !fwurl) {
|
||||
error("ERROR: can't get URL for latest firmware\n");
|
||||
logger(LL_ERROR, "can't get URL for latest firmware\n");
|
||||
return -1;
|
||||
}
|
||||
char* fwfn = strrchr(fwurl, '/');
|
||||
if (!fwfn) {
|
||||
error("ERROR: can't get local filename for firmware ipsw\n");
|
||||
logger(LL_ERROR, "can't get local filename for firmware ipsw\n");
|
||||
return -2;
|
||||
}
|
||||
fwfn++;
|
||||
|
||||
info("Latest firmware is %s\n", fwfn);
|
||||
logger(LL_INFO, "Latest firmware is %s\n", fwfn);
|
||||
|
||||
int res = ipsw_download_fw(fwurl, isha1, todir, ipswfile);
|
||||
|
||||
@@ -1390,14 +1418,14 @@ ipsw_file_handle_t ipsw_file_open(ipsw_archive_t ipsw, const char* path)
|
||||
int err = 0;
|
||||
struct zip *zip = zip_open(ipsw->path, 0, &err);
|
||||
if (zip == NULL) {
|
||||
error("ERROR: zip_open: %s: %d\n", ipsw->path, err);
|
||||
logger(LL_ERROR, "zip_open: %s: %d\n", ipsw->path, err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zip_stat_t zst;
|
||||
zip_int64_t zindex = zip_name_locate(zip, path, 0);
|
||||
if (zindex < 0) {
|
||||
error("ERROR: zip_name_locate: %s not found\n", path);
|
||||
logger(LL_ERROR, "zip_name_locate: %s not found\n", path);
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
free(handle);
|
||||
@@ -1405,7 +1433,7 @@ ipsw_file_handle_t ipsw_file_open(ipsw_archive_t ipsw, const char* path)
|
||||
}
|
||||
handle->zfile = zip_fopen_index(zip, zindex, 0);
|
||||
if (handle->zfile == NULL) {
|
||||
error("ERROR: zip_fopen_index: %s could not be opened\n", path);
|
||||
logger(LL_ERROR, "zip_fopen_index: %s could not be opened\n", path);
|
||||
zip_unchange_all(zip);
|
||||
zip_close(zip);
|
||||
free(handle);
|
||||
@@ -1422,7 +1450,7 @@ ipsw_file_handle_t ipsw_file_open(ipsw_archive_t ipsw, const char* path)
|
||||
handle->file = fopen(filepath, "rb");
|
||||
free(filepath);
|
||||
if (!handle->file) {
|
||||
error("ERROR: fopen: %s could not be opened\n", path);
|
||||
logger(LL_ERROR, "fopen: %s could not be opened\n", path);
|
||||
free(handle);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1461,7 +1489,7 @@ int64_t ipsw_file_read(ipsw_file_handle_t handle, void* buffer, size_t size)
|
||||
} else if (handle && handle->file) {
|
||||
return fread(buffer, 1, size, handle->file);
|
||||
} else {
|
||||
error("ERROR: %s: Invalid file handle\n", __func__);
|
||||
logger(LL_ERROR, "%s: Invalid file handle\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1480,7 +1508,7 @@ int ipsw_file_seek(ipsw_file_handle_t handle, int64_t offset, int whence)
|
||||
return fseeko(handle->file, offset, whence);
|
||||
#endif
|
||||
} else {
|
||||
error("ERROR: %s: Invalid file handle\n", __func__);
|
||||
logger(LL_ERROR, "%s: Invalid file handle\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1496,7 +1524,7 @@ int64_t ipsw_file_tell(ipsw_file_handle_t handle)
|
||||
return ftello(handle->file);
|
||||
#endif
|
||||
} else {
|
||||
error("ERROR: %s: Invalid file handle\n", __func__);
|
||||
logger(LL_ERROR, "%s: Invalid file handle\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
+11
-11
@@ -78,7 +78,7 @@ int limera1n_exploit(struct irecv_device *device, irecv_client_t *pclient)
|
||||
stack_address = 0x84033F98;
|
||||
shellcode_address = 0x84023001;
|
||||
} else {
|
||||
error("Unsupported ChipID 0x%04x. Can't exploit with limera1n.\n", device->chip_id);
|
||||
logger(LL_ERROR, "Unsupported ChipID 0x%04x. Can't exploit with limera1n.\n", device->chip_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -87,10 +87,10 @@ int limera1n_exploit(struct irecv_device *device, irecv_client_t *pclient)
|
||||
|
||||
irecv_client_t client = *pclient;
|
||||
|
||||
debug("Resetting device counters\n");
|
||||
logger(LL_DEBUG, "Resetting device counters\n");
|
||||
err = irecv_reset_counters(client);
|
||||
if (err != IRECV_E_SUCCESS) {
|
||||
error("%s\n", irecv_strerror(err));
|
||||
logger(LL_ERROR, "%s\n", irecv_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ int limera1n_exploit(struct irecv_device *device, irecv_client_t *pclient)
|
||||
heap[3] = stack_address;
|
||||
}
|
||||
|
||||
debug("Sending chunk headers\n");
|
||||
logger(LL_DEBUG, "Sending chunk headers\n");
|
||||
irecv_usb_control_transfer(client, 0x21, 1, 0, 0, buf, 0x800, 1000);
|
||||
|
||||
memset(buf, 0xCC, 0x800);
|
||||
@@ -111,32 +111,32 @@ int limera1n_exploit(struct irecv_device *device, irecv_client_t *pclient)
|
||||
irecv_usb_control_transfer(client, 0x21, 1, 0, 0, buf, 0x800, 1000);
|
||||
}
|
||||
|
||||
debug("Sending exploit payload\n");
|
||||
logger(LL_DEBUG, "Sending exploit payload\n");
|
||||
irecv_usb_control_transfer(client, 0x21, 1, 0, 0, shellcode, 0x800, 1000);
|
||||
|
||||
debug("Sending fake data\n");
|
||||
logger(LL_DEBUG, "Sending fake data\n");
|
||||
memset(buf, 0xBB, 0x800);
|
||||
irecv_usb_control_transfer(client, 0xA1, 1, 0, 0, buf, 0x800, 1000);
|
||||
irecv_usb_control_transfer(client, 0x21, 1, 0, 0, buf, 0x800, 10);
|
||||
|
||||
//debug("Executing exploit\n");
|
||||
//logger(LL_DEBUG, "Executing exploit\n");
|
||||
irecv_usb_control_transfer(client, 0x21, 2, 0, 0, buf, 0, 1000);
|
||||
|
||||
irecv_reset(client);
|
||||
irecv_finish_transfer(client);
|
||||
debug("Exploit sent\n");
|
||||
logger(LL_DEBUG, "Exploit sent\n");
|
||||
|
||||
debug("Reconnecting to device\n");
|
||||
logger(LL_DEBUG, "Reconnecting to device\n");
|
||||
*pclient = irecv_reconnect(client, 7);
|
||||
if (*pclient == NULL) {
|
||||
error("Unable to reconnect\n");
|
||||
logger(LL_ERROR, "Unable to reconnect\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
irecv_get_mode((*pclient), &mode);
|
||||
|
||||
if (mode != IRECV_K_DFU_MODE) {
|
||||
error("Device reconnected in non-DFU mode\n");
|
||||
logger(LL_ERROR, "Device reconnected in non-DFU mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -35,7 +35,7 @@ int lock_file(const char* filename, lock_info_t* lockinfo)
|
||||
#ifdef WIN32
|
||||
lockinfo->fp = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (lockinfo->fp == INVALID_HANDLE_VALUE) {
|
||||
debug("ERROR: could not open or create lockfile '%s'\n", filename);
|
||||
logger(LL_DEBUG, "ERROR: could not open or create lockfile '%s'\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ int lock_file(const char* filename, lock_info_t* lockinfo)
|
||||
lockinfo->ldata.OffsetHigh = 0;
|
||||
|
||||
if (!LockFileEx(lockinfo->fp, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &lockinfo->ldata)) {
|
||||
debug("ERROR: can't lock file, error %d\n", GetLastError());
|
||||
logger(LL_DEBUG, "ERROR: can't lock file, error %d\n", GetLastError());
|
||||
CloseHandle(lockinfo->fp);
|
||||
lockinfo->fp = INVALID_HANDLE_VALUE;
|
||||
return -1;
|
||||
@@ -52,7 +52,7 @@ int lock_file(const char* filename, lock_info_t* lockinfo)
|
||||
lockinfo->fp = fopen(filename, "a+");
|
||||
|
||||
if (!lockinfo->fp) {
|
||||
debug("ERROR: could not open or create lockfile '%s'\n", filename);
|
||||
logger(LL_DEBUG, "ERROR: could not open or create lockfile '%s'\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ int lock_file(const char* filename, lock_info_t* lockinfo)
|
||||
lockinfo->ldata.l_len = 0;
|
||||
|
||||
if (fcntl(fileno(lockinfo->fp), F_SETLKW, &lockinfo->ldata) < 0) {
|
||||
debug("ERROR: can't lock file, error %d\n", errno);
|
||||
logger(LL_DEBUG, "ERROR: can't lock file, error %d\n", errno);
|
||||
fclose(lockinfo->fp);
|
||||
lockinfo->fp = NULL;
|
||||
return -1;
|
||||
@@ -85,7 +85,7 @@ int unlock_file(lock_info_t* lockinfo)
|
||||
lockinfo->ldata.OffsetHigh = 0;
|
||||
|
||||
if (!UnlockFileEx(lockinfo->fp, 0, 1, 0, &lockinfo->ldata)) {
|
||||
debug("ERROR: can't unlock file, error %d\n", GetLastError());
|
||||
logger(LL_DEBUG, "ERROR: can't unlock file, error %d\n", GetLastError());
|
||||
CloseHandle(lockinfo->fp);
|
||||
lockinfo->fp = INVALID_HANDLE_VALUE;
|
||||
return -1;
|
||||
@@ -103,7 +103,7 @@ int unlock_file(lock_info_t* lockinfo)
|
||||
lockinfo->ldata.l_len = 0;
|
||||
|
||||
if (fcntl(fileno(lockinfo->fp), F_SETLK, &lockinfo->ldata) < 0) {
|
||||
debug("ERROR: can't unlock file, error %d\n", errno);
|
||||
logger(LL_DEBUG, "ERROR: can't unlock file, error %d\n", errno);
|
||||
fclose(lockinfo->fp);
|
||||
lockinfo->fp = NULL;
|
||||
return -1;
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* log.c
|
||||
*
|
||||
* Copyright (c) 2024 Nikias Bassen. 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
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include <libimobiledevice-glue/thread.h>
|
||||
#include <plist/plist.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
static int stderr_enabled = 1;
|
||||
|
||||
int log_level = LL_VERBOSE;
|
||||
int print_level = LL_INFO;
|
||||
|
||||
static void (*print_func)(int level, const char* fmt, va_list) = NULL;
|
||||
|
||||
const char *_level_label[6] = {
|
||||
" <Error>",
|
||||
"<Warning>",
|
||||
" <Notice>",
|
||||
" <Info>",
|
||||
"<Verbose>",
|
||||
" <Debug>"
|
||||
};
|
||||
|
||||
// Reference: https://stackoverflow.com/a/2390626/1806760
|
||||
// Initializer/finalizer sample for MSVC and GCC/Clang.
|
||||
// 2010-2016 Joe Lowe. Released into the public domain.
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define INITIALIZER(f) \
|
||||
static void f(void); \
|
||||
struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
|
||||
static void f(void)
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma section(".CRT$XCU",read)
|
||||
#define INITIALIZER2_(f,p) \
|
||||
static void f(void); \
|
||||
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
|
||||
__pragma(comment(linker,"/include:" p #f "_")) \
|
||||
static void f(void)
|
||||
#ifdef _WIN64
|
||||
#define INITIALIZER(f) INITIALIZER2_(f,"")
|
||||
#else
|
||||
#define INITIALIZER(f) INITIALIZER2_(f,"_")
|
||||
#endif
|
||||
#else
|
||||
#define INITIALIZER(f) \
|
||||
static void f(void) __attribute__((__constructor__)); \
|
||||
static void f(void)
|
||||
#endif
|
||||
|
||||
static mutex_t log_mutex;
|
||||
|
||||
static void logger_deinit(void)
|
||||
{
|
||||
mutex_destroy(&log_mutex);
|
||||
}
|
||||
|
||||
INITIALIZER(logger_init)
|
||||
{
|
||||
mutex_init(&log_mutex);
|
||||
atexit(logger_deinit);
|
||||
}
|
||||
|
||||
void logger(enum loglevel level, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *fs;
|
||||
|
||||
if (level > log_level)
|
||||
return;
|
||||
|
||||
mutex_lock(&log_mutex);
|
||||
|
||||
size_t fslen = 24 + strlen(fmt);
|
||||
fs = malloc(fslen);
|
||||
|
||||
#ifdef _WIN32
|
||||
SYSTEMTIME lt;
|
||||
GetLocalTime(<);
|
||||
snprintf(fs, 24, "%02d:%02d:%02d.%03d", lt.wHour, lt.wMinute, lt.wSecond, lt.wMilliseconds);
|
||||
#else
|
||||
struct timeval ts;
|
||||
struct tm tp_;
|
||||
struct tm *tp;
|
||||
|
||||
gettimeofday(&ts, NULL);
|
||||
#ifdef HAVE_LOCALTIME_R
|
||||
tp = localtime_r(&ts.tv_sec, &tp_);
|
||||
#else
|
||||
tp = localtime(&ts.tv_sec);
|
||||
#endif
|
||||
|
||||
strftime(fs, 9, "%H:%M:%S", tp);
|
||||
snprintf(fs+8, fslen-8, ".%03d %s %s", (int)(ts.tv_usec / 1000), _level_label[level], fmt);
|
||||
#endif
|
||||
|
||||
va_start(ap, fmt);
|
||||
if (print_func) {
|
||||
if (stderr_enabled) {
|
||||
vfprintf(stderr, fs, ap);
|
||||
fflush(stderr);
|
||||
}
|
||||
if (level <= print_level) {
|
||||
// skip the timestamp and log level string
|
||||
print_func(level, fs+23, ap);
|
||||
}
|
||||
} else {
|
||||
vprintf(fs, ap);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
free(fs);
|
||||
|
||||
mutex_unlock(&log_mutex);
|
||||
}
|
||||
|
||||
void logger_dump_hex(enum loglevel level, const void* buf, unsigned int len)
|
||||
{
|
||||
char *fs;
|
||||
|
||||
if (level > log_level)
|
||||
return;
|
||||
|
||||
mutex_lock(&log_mutex);
|
||||
|
||||
fs = (char*)malloc(len * 3 + 1);
|
||||
for (unsigned int i = 0; i < len; i++) {
|
||||
snprintf(fs + i*3, 3, "%02x%c", ((unsigned char*)buf)[i], (i < len-1) ? ' ' : '\n');
|
||||
}
|
||||
if (print_func) {
|
||||
if (stderr_enabled) {
|
||||
fprintf(stderr, "%s", fs);
|
||||
fflush(stderr);
|
||||
}
|
||||
if (level <= print_level) {
|
||||
print_func(level, "%s", fs);
|
||||
}
|
||||
} else {
|
||||
printf("%s", fs);
|
||||
}
|
||||
free(fs);
|
||||
|
||||
mutex_unlock(&log_mutex);
|
||||
}
|
||||
|
||||
void logger_dump_plist(enum loglevel level, plist_t plist, int human_readable)
|
||||
{
|
||||
if (level > log_level)
|
||||
return;
|
||||
mutex_lock(&log_mutex);
|
||||
plist_write_to_stream(plist, stderr_enabled ? stderr : stdout, (human_readable) ? PLIST_FORMAT_PRINT : PLIST_FORMAT_XML, PLIST_OPT_NONE);
|
||||
mutex_unlock(&log_mutex);
|
||||
}
|
||||
|
||||
int logger_set_logfile(const char* path)
|
||||
{
|
||||
if (!path || !strcasecmp(path, "NULL") || !strcasecmp(path, "NONE")) {
|
||||
stderr_enabled = 0;
|
||||
return 0;
|
||||
}
|
||||
stderr_enabled = 1;
|
||||
if (strcmp(path, "-")) {
|
||||
FILE* newf = freopen(path, "w", stderr);
|
||||
if (!newf) {
|
||||
logger(LL_ERROR, "Could not open logfile '%s': %s\n", path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void logger_set_print_func(void (*func)(int, const char*, va_list))
|
||||
{
|
||||
print_func = func;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* log.h
|
||||
*
|
||||
* Copyright (c) 2024 Nikias Bassen. 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
|
||||
*/
|
||||
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
enum loglevel {
|
||||
LL_ERROR = 0,
|
||||
LL_WARNING,
|
||||
LL_NOTICE,
|
||||
LL_INFO,
|
||||
LL_VERBOSE,
|
||||
LL_DEBUG
|
||||
};
|
||||
|
||||
extern int log_level;
|
||||
|
||||
void logger(enum loglevel level, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
int logger_set_logfile(const char* path);
|
||||
void logger_set_print_func(void (*func)(int level, const char*, va_list));
|
||||
void logger_dump_hex(enum loglevel level, const void* buf, unsigned int len);
|
||||
void logger_dump_plist(enum loglevel level, plist_t plist, int human_readable);
|
||||
|
||||
#endif
|
||||
@@ -54,10 +54,10 @@ mbn_file* mbn_parse(unsigned char* data, unsigned int size)
|
||||
// we cheat here since we don't parse the actual ELF file
|
||||
mbn->parsed_size = mbn->size;
|
||||
} else {
|
||||
debug("DEBUG: Unknown file format passed to %s\n", __func__);
|
||||
logger(LL_DEBUG, "Unknown file format passed to %s\n", __func__);
|
||||
}
|
||||
if (mbn->parsed_size != mbn->size) {
|
||||
info("WARNING: size mismatch when parsing MBN file. Continuing anyway.\n");
|
||||
logger(LL_WARNING, "Size mismatch when parsing MBN file. Continuing anyway.\n");
|
||||
}
|
||||
return mbn;
|
||||
}
|
||||
@@ -75,12 +75,12 @@ void mbn_free(mbn_file* mbn)
|
||||
int mbn_update_sig_blob(mbn_file* mbn, const unsigned char* sigdata, unsigned int siglen)
|
||||
{
|
||||
if (!mbn) {
|
||||
error("ERROR: %s: no data\n", __func__);
|
||||
logger(LL_ERROR, "%s: no data\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
mbn->parsed_sig_offset = mbn->size - siglen;
|
||||
if ((mbn->parsed_sig_offset + siglen) > mbn->size) {
|
||||
error("ERROR: %s: signature is larger than mbn file size\n", __func__);
|
||||
logger(LL_ERROR, "%s: signature is larger than mbn file size\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
+60
-56
@@ -49,12 +49,12 @@ static int normal_idevice_new(struct idevicerestore_client_t* client, idevice_t*
|
||||
if (client->udid) {
|
||||
device_error = idevice_new(&dev, client->udid);
|
||||
if (device_error != IDEVICE_E_SUCCESS) {
|
||||
debug("%s: can't open device with UDID %s\n", __func__, client->udid);
|
||||
logger(LL_DEBUG, "%s: can't open device with UDID %s\n", __func__, client->udid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lockdownd_client_new(dev, &lockdown, "idevicerestore") != LOCKDOWN_E_SUCCESS) {
|
||||
error("ERROR: %s: can't connect to lockdownd on device with UDID %s\n", __func__, client->udid);
|
||||
logger(LL_ERROR, "%s: can't connect to lockdownd on device with UDID %s\n", __func__, client->udid);
|
||||
return -1;
|
||||
|
||||
}
|
||||
@@ -94,12 +94,12 @@ static int normal_idevice_new(struct idevicerestore_client_t* client, idevice_t*
|
||||
}
|
||||
device_error = idevice_new(&dev, devices[j]);
|
||||
if (device_error != IDEVICE_E_SUCCESS) {
|
||||
debug("%s: can't open device with UDID %s\n", __func__, devices[j]);
|
||||
logger(LL_DEBUG, "%s: can't open device with UDID %s\n", __func__, devices[j]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lockdownd_client_new(dev, &lockdown, "idevicerestore") != LOCKDOWN_E_SUCCESS) {
|
||||
error("ERROR: %s: can't connect to lockdownd on device with UDID %s\n", __func__, devices[j]);
|
||||
logger(LL_ERROR, "%s: can't connect to lockdownd on device with UDID %s\n", __func__, devices[j]);
|
||||
continue;
|
||||
|
||||
}
|
||||
@@ -170,10 +170,7 @@ irecv_device_t normal_get_irecv_device(struct idevicerestore_client_t* client)
|
||||
|
||||
lockdown_error = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore");
|
||||
if (!(client->flags & FLAG_ERASE) && lockdown_error == LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING) {
|
||||
info("*** Device is not paired with this computer. Please trust this computer on the device to continue. ***\n");
|
||||
if (client->flags & FLAG_DEBUG) {
|
||||
idevice_set_debug_level(0);
|
||||
}
|
||||
show_banner("Device is not paired with this computer. Please trust this computer on the device to continue.\n");
|
||||
while (!(client->flags & FLAG_QUIT)) {
|
||||
lockdown_error = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore");
|
||||
if (lockdown_error != LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING) {
|
||||
@@ -181,9 +178,7 @@ irecv_device_t normal_get_irecv_device(struct idevicerestore_client_t* client)
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
if (client->flags & FLAG_DEBUG) {
|
||||
idevice_set_debug_level(1);
|
||||
}
|
||||
hide_banner();
|
||||
if (client->flags & FLAG_QUIT) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -223,13 +218,13 @@ int normal_enter_recovery(struct idevicerestore_client_t* client)
|
||||
|
||||
device_error = idevice_new(&device, client->udid);
|
||||
if (device_error != IDEVICE_E_SUCCESS) {
|
||||
error("ERROR: Unable to find device\n");
|
||||
logger(LL_ERROR, "Unable to find device\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lockdown_error = lockdownd_client_new(device, &lockdown, "idevicerestore");
|
||||
if (lockdown_error != LOCKDOWN_E_SUCCESS) {
|
||||
error("ERROR: Unable to connect to lockdownd: %s (%d)\n", lockdownd_strerror(lockdown_error), lockdown_error);
|
||||
logger(LL_ERROR, "Unable to connect to lockdownd: %s (%d)\n", lockdownd_strerror(lockdown_error), lockdown_error);
|
||||
idevice_free(device);
|
||||
return -1;
|
||||
}
|
||||
@@ -239,14 +234,14 @@ int normal_enter_recovery(struct idevicerestore_client_t* client)
|
||||
lockdownd_client_free(lockdown);
|
||||
lockdown = NULL;
|
||||
if (LOCKDOWN_E_SUCCESS != (lockdown_error = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore"))) {
|
||||
error("ERROR: Could not connect to lockdownd: %s (%d)\n", lockdownd_strerror(lockdown_error), lockdown_error);
|
||||
logger(LL_ERROR, "Could not connect to lockdownd: %s (%d)\n", lockdownd_strerror(lockdown_error), lockdown_error);
|
||||
idevice_free(device);
|
||||
return -1;
|
||||
}
|
||||
lockdown_error = lockdownd_enter_recovery(lockdown);
|
||||
}
|
||||
if (lockdown_error != LOCKDOWN_E_SUCCESS) {
|
||||
error("ERROR: Unable to place device in recovery mode: %s (%d)\n", lockdownd_strerror(lockdown_error), lockdown_error);
|
||||
logger(LL_ERROR, "Unable to place device in recovery mode: %s (%d)\n", lockdownd_strerror(lockdown_error), lockdown_error);
|
||||
lockdownd_client_free(lockdown);
|
||||
idevice_free(device);
|
||||
return -1;
|
||||
@@ -258,25 +253,25 @@ int normal_enter_recovery(struct idevicerestore_client_t* client)
|
||||
device = NULL;
|
||||
|
||||
mutex_lock(&client->device_event_mutex);
|
||||
debug("DEBUG: Waiting for device to disconnect...\n");
|
||||
logger(LL_DEBUG, "Waiting for device to disconnect...\n");
|
||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 60000);
|
||||
if (client->mode == MODE_NORMAL || (client->flags & FLAG_QUIT)) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Failed to place device in recovery mode\n");
|
||||
logger(LL_ERROR, "Failed to place device in recovery mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
debug("DEBUG: Waiting for device to connect in recovery mode...\n");
|
||||
logger(LL_DEBUG, "Waiting for device to connect in recovery mode...\n");
|
||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 60000);
|
||||
if (client->mode != MODE_RECOVERY || (client->flags & FLAG_QUIT)) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Failed to enter recovery mode\n");
|
||||
logger(LL_ERROR, "Failed to enter recovery mode\n");
|
||||
return -1;
|
||||
}
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
|
||||
if (recovery_client_new(client) < 0) {
|
||||
error("ERROR: Unable to enter recovery mode\n");
|
||||
logger(LL_ERROR, "Unable to enter recovery mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -296,20 +291,20 @@ plist_t normal_get_lockdown_value(struct idevicerestore_client_t* client, const
|
||||
|
||||
device_error = idevice_new(&device, client->udid);
|
||||
if (device_error != IDEVICE_E_SUCCESS) {
|
||||
error("ERROR: Unable to connect to device?!\n");
|
||||
logger(LL_ERROR, "Unable to connect to device?!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lockdown_error = lockdownd_client_new(device, &lockdown, "idevicerestore");
|
||||
if (lockdown_error != LOCKDOWN_E_SUCCESS) {
|
||||
error("ERROR: Unable to connect to lockdownd\n");
|
||||
logger(LL_ERROR, "Unable to connect to lockdownd\n");
|
||||
idevice_free(device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lockdown_error = lockdownd_get_value(lockdown, domain, key, &node);
|
||||
if (lockdown_error != LOCKDOWN_E_SUCCESS) {
|
||||
debug("ERROR: Unable to get %s-%s from lockdownd\n", domain, key);
|
||||
logger(LL_DEBUG, "ERROR: Unable to get %s-%s from lockdownd\n", domain, key);
|
||||
lockdownd_client_free(lockdown);
|
||||
idevice_free(device);
|
||||
return NULL;
|
||||
@@ -328,7 +323,7 @@ static int normal_get_nonce_by_key(struct idevicerestore_client_t* client, const
|
||||
plist_t nonce_node = normal_get_lockdown_value(client, NULL, key);
|
||||
|
||||
if (!nonce_node || plist_get_node_type(nonce_node) != PLIST_DATA) {
|
||||
error("Unable to get %s\n", key);
|
||||
logger(LL_ERROR, "Unable to get %s\n", key);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -389,12 +384,12 @@ int normal_get_firmware_preflight_info(struct idevicerestore_client_t* client, p
|
||||
if (has_telephony_capability) {
|
||||
node = normal_get_lockdown_value(client, NULL, "FirmwarePreflightInfo");
|
||||
if (!node || plist_get_node_type(node) != PLIST_DICT) {
|
||||
error("ERROR: Unable to get FirmwarePreflightInfo\n");
|
||||
logger(LL_ERROR, "Unable to get FirmwarePreflightInfo\n");
|
||||
return -1;
|
||||
}
|
||||
*preflight_info = node;
|
||||
} else {
|
||||
debug("DEBUG: Device does not have TelephonyCapability, no FirmwarePreflightInfo\n");
|
||||
logger(LL_DEBUG, "Device does not have TelephonyCapability, no FirmwarePreflightInfo\n");
|
||||
*preflight_info = NULL;
|
||||
}
|
||||
|
||||
@@ -407,7 +402,7 @@ int normal_get_preflight_info(struct idevicerestore_client_t* client, plist_t *p
|
||||
if (PLIST_IS_DICT(node)) {
|
||||
*preflight_info = node;
|
||||
} else {
|
||||
debug("DEBUG: No PreflightInfo available.\n");
|
||||
logger(LL_DEBUG, "No PreflightInfo available.\n");
|
||||
*preflight_info = NULL;
|
||||
}
|
||||
return 0;
|
||||
@@ -427,20 +422,25 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_
|
||||
|
||||
device_err = idevice_new(&device, client->udid);
|
||||
if (device_err != IDEVICE_E_SUCCESS) {
|
||||
error("ERROR: Could not connect to device (%d)\n", device_err);
|
||||
logger(LL_ERROR, "Could not connect to device (%d)\n", device_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lerr = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore");
|
||||
if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) {
|
||||
logger(LL_ERROR, "Device is locked. Unlock device and try again.\n");
|
||||
idevice_free(device);
|
||||
return -1;
|
||||
}
|
||||
if (lerr != LOCKDOWN_E_SUCCESS) {
|
||||
error("ERROR: Could not connect to lockdownd (%d)\n", lerr);
|
||||
logger(LL_ERROR, "Could not connect to lockdownd (%d)\n", lerr);
|
||||
idevice_free(device);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lerr = lockdownd_start_service(lockdown, PREBOARD_SERVICE_NAME, &service);
|
||||
if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) {
|
||||
info("*** Device is locked. Please unlock the device to continue. ***\n");
|
||||
show_banner("Device is locked. Please unlock the device to continue.\n");
|
||||
while (1) {
|
||||
lerr = lockdownd_start_service(lockdown, PREBOARD_SERVICE_NAME, &service);
|
||||
if (lerr != LOCKDOWN_E_PASSWORD_PROTECTED) {
|
||||
@@ -451,7 +451,7 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_
|
||||
}
|
||||
|
||||
if (lerr != LOCKDOWN_E_SUCCESS) {
|
||||
error("ERROR: Could not start preboard service (%d)\n", lerr);
|
||||
logger(LL_ERROR, "Could not start preboard service (%d)\n", lerr);
|
||||
lockdownd_client_free(lockdown);
|
||||
idevice_free(device);
|
||||
return -1;
|
||||
@@ -461,14 +461,14 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_
|
||||
lockdownd_service_descriptor_free(service);
|
||||
lockdownd_client_free(lockdown);
|
||||
if (perr != PREBOARD_E_SUCCESS) {
|
||||
error("ERROR: Could not connect to preboard service (%d)\n", perr);
|
||||
logger(LL_ERROR, "Could not connect to preboard service (%d)\n", perr);
|
||||
idevice_free(device);
|
||||
return -1;
|
||||
}
|
||||
|
||||
perr = preboard_create_stashbag(preboard, manifest, NULL, NULL);
|
||||
if (perr != PREBOARD_E_SUCCESS) {
|
||||
error("ERROR: Failed to trigger stashbag creation (%d)\n", perr);
|
||||
logger(LL_ERROR, "Failed to trigger stashbag creation (%d)\n", perr);
|
||||
preboard_client_free(preboard);
|
||||
idevice_free(device);
|
||||
return -1;
|
||||
@@ -481,25 +481,25 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_
|
||||
if (perr == PREBOARD_E_TIMEOUT) {
|
||||
continue;
|
||||
} else if (perr != PREBOARD_E_SUCCESS) {
|
||||
error("ERROR: could not receive from preboard service\n");
|
||||
logger(LL_ERROR, "could not receive from preboard service\n");
|
||||
break;
|
||||
} else {
|
||||
plist_t node;
|
||||
|
||||
if (plist_dict_get_bool(pl, "Skip")) {
|
||||
result = 0;
|
||||
info("Device does not require stashbag.\n");
|
||||
logger(LL_INFO, "Device does not require stashbag.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (plist_dict_get_bool(pl, "ShowDialog")) {
|
||||
info("Device requires stashbag.\n");
|
||||
printf("******************************************************************************\n"
|
||||
"* Please enter your passcode on the device. The device will store a token *\n"
|
||||
"* that will be used after restore to access the user data partition. This *\n"
|
||||
"* prevents an 'Attempting data recovery' process occurring after reboot that *\n"
|
||||
"* may take a long time to complete and will _also_ require the passcode. *\n"
|
||||
"******************************************************************************\n");
|
||||
logger(LL_INFO, "Device requires stashbag.\n");
|
||||
show_banner(
|
||||
"Please enter your passcode on the device. The device will store a token\n"
|
||||
"that will be used after restore to access the user data partition. This\n"
|
||||
"prevents an 'Attempting data recovery' process occurring after reboot that\n"
|
||||
"may take a long time to complete and will _also_ require the passcode."
|
||||
);
|
||||
plist_free(pl);
|
||||
continue;
|
||||
}
|
||||
@@ -510,13 +510,13 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_
|
||||
if (node) {
|
||||
plist_get_string_val(node, &strval);
|
||||
}
|
||||
error("ERROR: Could not create stashbag: %s\n", (strval) ? strval : "(Unknown error)");
|
||||
logger(LL_ERROR, "Could not create stashbag: %s\n", (strval) ? strval : "(Unknown error)");
|
||||
free(strval);
|
||||
plist_free(pl);
|
||||
break;
|
||||
}
|
||||
if (plist_dict_get_bool(pl, "Timeout")) {
|
||||
error("ERROR: Timeout while waiting for user to enter passcode.\n");
|
||||
logger(LL_ERROR, "Timeout while waiting for user to enter passcode.\n");
|
||||
result = -2;
|
||||
plist_free(pl);
|
||||
break;
|
||||
@@ -525,12 +525,15 @@ int normal_handle_create_stashbag(struct idevicerestore_client_t* client, plist_
|
||||
plist_free(pl);
|
||||
/* hide dialog */
|
||||
result = 1;
|
||||
info("Stashbag created.\n");
|
||||
logger(LL_INFO, "Stashbag created.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
plist_free(pl);
|
||||
}
|
||||
|
||||
hide_banner();
|
||||
|
||||
preboard_client_free(preboard);
|
||||
idevice_free(device);
|
||||
|
||||
@@ -552,20 +555,20 @@ int normal_handle_commit_stashbag(struct idevicerestore_client_t* client, plist_
|
||||
|
||||
device_err = idevice_new(&device, client->udid);
|
||||
if (device_err != IDEVICE_E_SUCCESS) {
|
||||
error("ERROR: Could not connect to device (%d)\n", device_err);
|
||||
logger(LL_ERROR, "Could not connect to device (%d)\n", device_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lerr = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore");
|
||||
if (lerr != LOCKDOWN_E_SUCCESS) {
|
||||
error("ERROR: Could not connect to lockdownd (%d)\n", lerr);
|
||||
logger(LL_ERROR, "Could not connect to lockdownd (%d)\n", lerr);
|
||||
idevice_free(device);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lerr = lockdownd_start_service(lockdown, PREBOARD_SERVICE_NAME, &service);
|
||||
if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) {
|
||||
info("*** Device is locked. Please unlock the device to continue. ***\n");
|
||||
show_banner("Device is locked. Please unlock the device to continue.\n");
|
||||
while (1) {
|
||||
lerr = lockdownd_start_service(lockdown, PREBOARD_SERVICE_NAME, &service);
|
||||
if (lerr != LOCKDOWN_E_PASSWORD_PROTECTED) {
|
||||
@@ -573,10 +576,11 @@ int normal_handle_commit_stashbag(struct idevicerestore_client_t* client, plist_
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
hide_banner();
|
||||
}
|
||||
|
||||
if (lerr != LOCKDOWN_E_SUCCESS) {
|
||||
error("ERROR: Could not start preboard service (%d)\n", lerr);
|
||||
logger(LL_ERROR, "Could not start preboard service (%d)\n", lerr);
|
||||
lockdownd_client_free(lockdown);
|
||||
idevice_free(device);
|
||||
return -1;
|
||||
@@ -586,14 +590,14 @@ int normal_handle_commit_stashbag(struct idevicerestore_client_t* client, plist_
|
||||
lockdownd_service_descriptor_free(service);
|
||||
lockdownd_client_free(lockdown);
|
||||
if (perr != PREBOARD_E_SUCCESS) {
|
||||
error("ERROR: Could not connect to preboard service (%d)\n", perr);
|
||||
logger(LL_ERROR, "Could not connect to preboard service (%d)\n", perr);
|
||||
idevice_free(device);
|
||||
return -1;
|
||||
}
|
||||
|
||||
perr = preboard_commit_stashbag(preboard, manifest, NULL, NULL);
|
||||
if (perr != PREBOARD_E_SUCCESS) {
|
||||
error("ERROR: Failed to trigger stashbag creation (%d)\n", perr);
|
||||
logger(LL_ERROR, "Failed to trigger stashbag creation (%d)\n", perr);
|
||||
preboard_client_free(preboard);
|
||||
idevice_free(device);
|
||||
return -1;
|
||||
@@ -601,7 +605,7 @@ int normal_handle_commit_stashbag(struct idevicerestore_client_t* client, plist_
|
||||
|
||||
perr = preboard_receive_with_timeout(preboard, &pl, 30000);
|
||||
if (perr != PREBOARD_E_SUCCESS) {
|
||||
error("ERROR: could not receive from preboard service (%d)\n", perr);
|
||||
logger(LL_ERROR, "could not receive from preboard service (%d)\n", perr);
|
||||
} else {
|
||||
plist_t node = plist_dict_get_item(pl, "Error");
|
||||
if (node) {
|
||||
@@ -610,14 +614,14 @@ int normal_handle_commit_stashbag(struct idevicerestore_client_t* client, plist_
|
||||
if (node) {
|
||||
plist_get_string_val(node, &strval);
|
||||
}
|
||||
error("ERROR: Could not commit stashbag: %s\n", (strval) ? strval : "(Unknown error)");
|
||||
logger(LL_ERROR, "Could not commit stashbag: %s\n", (strval) ? strval : "(Unknown error)");
|
||||
free(strval);
|
||||
} else if (plist_dict_get_bool(pl, "StashbagCommitComplete")) {
|
||||
info("Stashbag committed!\n");
|
||||
logger(LL_INFO, "Stashbag committed!\n");
|
||||
result = 0;
|
||||
} else {
|
||||
error("ERROR: Unexpected reply from preboard service\n");
|
||||
debug_plist(pl);
|
||||
logger(LL_ERROR, "Unexpected reply from preboard service\n");
|
||||
logger_dump_plist(LL_VERBOSE, pl, 1);
|
||||
}
|
||||
plist_free(pl);
|
||||
}
|
||||
|
||||
+54
-52
@@ -39,14 +39,15 @@
|
||||
static int recovery_progress_callback(irecv_client_t client, const irecv_event_t* event)
|
||||
{
|
||||
if (event->type == IRECV_PROGRESS) {
|
||||
//print_progress_bar(event->progress);
|
||||
set_progress('RECV', (double)(event->progress/100.0));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void recovery_client_free(struct idevicerestore_client_t* client)
|
||||
{
|
||||
if(client) {
|
||||
if (client) {
|
||||
finalize_progress('RECV');
|
||||
if (client->recovery) {
|
||||
if(client->recovery->client) {
|
||||
irecv_close(client->recovery->client);
|
||||
@@ -68,7 +69,7 @@ int recovery_client_new(struct idevicerestore_client_t* client)
|
||||
if(client->recovery == NULL) {
|
||||
client->recovery = (struct recovery_client_t*)malloc(sizeof(struct recovery_client_t));
|
||||
if (client->recovery == NULL) {
|
||||
error("ERROR: Out of memory\n");
|
||||
logger(LL_ERROR, "Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
memset(client->recovery, 0, sizeof(struct recovery_client_t));
|
||||
@@ -81,23 +82,24 @@ int recovery_client_new(struct idevicerestore_client_t* client)
|
||||
}
|
||||
|
||||
if (i >= attempts) {
|
||||
error("ERROR: Unable to connect to device in recovery mode\n");
|
||||
logger(LL_ERROR, "Unable to connect to device in recovery mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sleep(4);
|
||||
debug("Retrying connection...\n");
|
||||
logger(LL_DEBUG, "Retrying connection...\n");
|
||||
}
|
||||
|
||||
if (client->srnm == NULL) {
|
||||
const struct irecv_device_info *device_info = irecv_get_device_info(recovery);
|
||||
if (device_info && device_info->srnm) {
|
||||
client->srnm = strdup(device_info->srnm);
|
||||
info("INFO: device serial number is %s\n", client->srnm);
|
||||
logger(LL_INFO, "INFO: device serial number is %s\n", client->srnm);
|
||||
}
|
||||
}
|
||||
|
||||
irecv_event_subscribe(recovery, IRECV_PROGRESS, &recovery_progress_callback, NULL);
|
||||
register_progress('RECV', "Uploading");
|
||||
client->recovery->client = recovery;
|
||||
return 0;
|
||||
}
|
||||
@@ -108,13 +110,13 @@ int recovery_set_autoboot(struct idevicerestore_client_t* client, int enable)
|
||||
|
||||
recovery_error = irecv_send_command(client->recovery->client, (enable) ? "setenv auto-boot true" : "setenv auto-boot false");
|
||||
if (recovery_error != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to set auto-boot environmental variable\n");
|
||||
logger(LL_ERROR, "Unable to set auto-boot environmental variable\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
recovery_error = irecv_send_command(client->recovery->client, "saveenv");
|
||||
if (recovery_error != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to save environmental variable\n");
|
||||
logger(LL_ERROR, "Unable to save environmental variable\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -124,7 +126,7 @@ int recovery_set_autoboot(struct idevicerestore_client_t* client, int enable)
|
||||
int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build_identity)
|
||||
{
|
||||
if (client->build_major >= 8) {
|
||||
client->restore_boot_args = strdup("rd=md0 nand-enable-reformat=1 -progress");
|
||||
client->restore_boot_args = strdup("rd=md0 nand-enable-reformat=1rogress");
|
||||
} else if (client->macos_variant) {
|
||||
client->restore_boot_args = strdup("rd=md0 nand-enable-reformat=1 -progress -restore");
|
||||
}
|
||||
@@ -141,21 +143,21 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build
|
||||
if (!client->image4supported) {
|
||||
/* send ApTicket */
|
||||
if (recovery_send_ticket(client) < 0) {
|
||||
error("ERROR: Unable to send APTicket\n");
|
||||
logger(LL_ERROR, "Unable to send APTicket\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info("Recovery Mode Environment:\n");
|
||||
logger(LL_INFO, "Recovery Mode Environment:\n");
|
||||
char* value = NULL;
|
||||
irecv_getenv(client->recovery->client, "build-version", &value);
|
||||
info("iBoot build-version=%s\n", (value) ? value : "(unknown)");
|
||||
logger(LL_INFO, "iBoot build-version=%s\n", (value) ? value : "(unknown)");
|
||||
free(value);
|
||||
value = NULL;
|
||||
|
||||
irecv_getenv(client->recovery->client, "build-style", &value);
|
||||
info("iBoot build-style=%s\n", (value) ? value : "(unknown)");
|
||||
logger(LL_INFO, "iBoot build-style=%s\n", (value) ? value : "(unknown)");
|
||||
free(value);
|
||||
value = NULL;
|
||||
|
||||
@@ -165,11 +167,11 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build
|
||||
boot_stage = strtoul(value, NULL, 0);
|
||||
}
|
||||
if (boot_stage > 0) {
|
||||
info("iBoot boot-stage=%s\n", value);
|
||||
logger(LL_INFO, "iBoot boot-stage=%s\n", value);
|
||||
free(value);
|
||||
value = NULL;
|
||||
if (boot_stage != 2) {
|
||||
error("ERROR: iBoot should be at boot stage 2, continuing anyway...\n");
|
||||
logger(LL_ERROR, "iBoot should be at boot stage 2, continuing anyway...\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,12 +181,12 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build
|
||||
radio_error = strtoul(value, NULL, 0);
|
||||
}
|
||||
if (radio_error > 0) {
|
||||
info("radio-error=%s\n", value);
|
||||
logger(LL_INFO, "radio-error=%s\n", value);
|
||||
free(value);
|
||||
value = NULL;
|
||||
irecv_getenv(client->recovery->client, "radio-error-string", &value);
|
||||
if (value) {
|
||||
info("radio-error-string=%s\n", value);
|
||||
logger(LL_INFO, "radio-error-string=%s\n", value);
|
||||
free(value);
|
||||
value = NULL;
|
||||
}
|
||||
@@ -196,32 +198,32 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build
|
||||
|
||||
/* send logo and show it */
|
||||
if (recovery_send_applelogo(client, build_identity) < 0) {
|
||||
error("ERROR: Unable to send AppleLogo\n");
|
||||
logger(LL_ERROR, "Unable to send AppleLogo\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* send components loaded by iBoot */
|
||||
if (recovery_send_loaded_by_iboot(client, build_identity) < 0) {
|
||||
error("ERROR: Unable to send components supposed to be loaded by iBoot\n");
|
||||
logger(LL_ERROR, "Unable to send components supposed to be loaded by iBoot\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* send ramdisk and run it */
|
||||
if (recovery_send_ramdisk(client, build_identity) < 0) {
|
||||
error("ERROR: Unable to send Ramdisk\n");
|
||||
logger(LL_ERROR, "Unable to send Ramdisk\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* send devicetree and load it */
|
||||
if (recovery_send_component_and_command(client, build_identity, "RestoreDeviceTree", "devicetree") < 0) {
|
||||
error("ERROR: Unable to send DeviceTree\n");
|
||||
logger(LL_ERROR, "Unable to send DeviceTree\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (build_identity_has_component(build_identity, "RestoreSEP")) {
|
||||
/* send rsepfirmware and load it */
|
||||
if (recovery_send_component_and_command(client, build_identity, "RestoreSEP", "rsepfirmware") < 0) {
|
||||
error("ERROR: Unable to send RestoreSEP\n");
|
||||
logger(LL_ERROR, "Unable to send RestoreSEP\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -229,15 +231,15 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build
|
||||
mutex_lock(&client->device_event_mutex);
|
||||
if (recovery_send_kernelcache(client, build_identity) < 0) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Unable to send KernelCache\n");
|
||||
logger(LL_ERROR, "Unable to send KernelCache\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
debug("DEBUG: Waiting for device to disconnect...\n");
|
||||
logger(LL_DEBUG, "Waiting for device to disconnect...\n");
|
||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 30000);
|
||||
if (client->mode == MODE_RECOVERY || (client->flags & FLAG_QUIT)) {
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
error("ERROR: Failed to place device in restore mode\n");
|
||||
logger(LL_ERROR, "Failed to place device in restore mode\n");
|
||||
return -1;
|
||||
}
|
||||
mutex_unlock(&client->device_event_mutex);
|
||||
@@ -248,28 +250,28 @@ int recovery_enter_restore(struct idevicerestore_client_t* client, plist_t build
|
||||
int recovery_send_ticket(struct idevicerestore_client_t* client)
|
||||
{
|
||||
if (!client->tss) {
|
||||
error("ERROR: ApTicket requested but no TSS present\n");
|
||||
logger(LL_ERROR, "ApTicket requested but no TSS present\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char* data = NULL;
|
||||
uint32_t size = 0;
|
||||
if (tss_response_get_ap_ticket(client->tss, &data, &size) < 0) {
|
||||
error("ERROR: Unable to get ApTicket from TSS request\n");
|
||||
logger(LL_ERROR, "Unable to get ApTicket from TSS request\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
info("Sending APTicket (%d bytes)\n", size);
|
||||
logger(LL_INFO, "Sending APTicket (%d bytes)\n", size);
|
||||
irecv_error_t err = irecv_send_buffer(client->recovery->client, data, size, 0);
|
||||
free(data);
|
||||
if (err != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to send APTicket: %s\n", irecv_strerror(err));
|
||||
logger(LL_ERROR, "Unable to send APTicket: %s\n", irecv_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = irecv_send_command(client->recovery->client, "ticket");
|
||||
if (err != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to send ticket command\n");
|
||||
logger(LL_ERROR, "Unable to send ticket command\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -285,12 +287,12 @@ int recovery_send_component(struct idevicerestore_client_t* client, plist_t buil
|
||||
|
||||
if (client->tss) {
|
||||
if (tss_response_get_path_by_entry(client->tss, component, &path) < 0) {
|
||||
debug("NOTE: No path for component %s in TSS, will fetch from build_identity\n", component);
|
||||
logger(LL_DEBUG, "No path for component %s in TSS, will fetch from build_identity\n", component);
|
||||
}
|
||||
}
|
||||
if (!path) {
|
||||
if (build_identity_get_component_path(build_identity, component, &path) < 0) {
|
||||
error("ERROR: Unable to get path for component '%s'\n", component);
|
||||
logger(LL_ERROR, "Unable to get path for component '%s'\n", component);
|
||||
free(path);
|
||||
return -1;
|
||||
}
|
||||
@@ -301,24 +303,24 @@ int recovery_send_component(struct idevicerestore_client_t* client, plist_t buil
|
||||
int ret = extract_component(client->ipsw, path, &component_data, &component_size);
|
||||
free(path);
|
||||
if (ret < 0) {
|
||||
error("ERROR: Unable to extract component: %s\n", component);
|
||||
logger(LL_ERROR, "Unable to extract component: %s\n", component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = personalize_component(client, component, component_data, component_size, client->tss, &data, &size);
|
||||
free(component_data);
|
||||
if (ret < 0) {
|
||||
error("ERROR: Unable to get personalized component: %s\n", component);
|
||||
logger(LL_ERROR, "Unable to get personalized component: %s\n", component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
info("Sending %s (%d bytes)...\n", component, size);
|
||||
logger(LL_INFO, "Sending %s (%d bytes)...\n", component, size);
|
||||
|
||||
// FIXME: Did I do this right????
|
||||
err = irecv_send_buffer(client->recovery->client, data, size, 0);
|
||||
free(data);
|
||||
if (err != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to send %s component: %s\n", component, irecv_strerror(err));
|
||||
logger(LL_ERROR, "Unable to send %s component: %s\n", component, irecv_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -330,13 +332,13 @@ int recovery_send_component_and_command(struct idevicerestore_client_t* client,
|
||||
irecv_error_t recovery_error = IRECV_E_SUCCESS;
|
||||
|
||||
if (recovery_send_component(client, build_identity, component) < 0) {
|
||||
error("ERROR: Unable to send %s to device.\n", component);
|
||||
logger(LL_ERROR, "Unable to send %s to device.\n", component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
recovery_error = irecv_send_command(client->recovery->client, command);
|
||||
if (recovery_error != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to execute %s\n", component);
|
||||
logger(LL_ERROR, "Unable to execute %s\n", component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -355,13 +357,13 @@ int recovery_send_ibec(struct idevicerestore_client_t* client, plist_t build_ide
|
||||
}
|
||||
|
||||
if (recovery_send_component(client, build_identity, component) < 0) {
|
||||
error("ERROR: Unable to send %s to device.\n", component);
|
||||
logger(LL_ERROR, "Unable to send %s to device.\n", component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
recovery_error = irecv_send_command_breq(client->recovery->client, "go", 1);
|
||||
if (recovery_error != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to execute %s\n", component);
|
||||
logger(LL_ERROR, "Unable to execute %s\n", component);
|
||||
return -1;
|
||||
}
|
||||
irecv_usb_control_transfer(client->recovery->client, 0x21, 1, 0, 0, 0, 0, 5000);
|
||||
@@ -378,7 +380,7 @@ int recovery_send_applelogo(struct idevicerestore_client_t* client, plist_t buil
|
||||
return 0;
|
||||
}
|
||||
|
||||
info("Sending %s...\n", component);
|
||||
logger(LL_INFO, "Sending %s...\n", component);
|
||||
if (client->recovery == NULL) {
|
||||
if (recovery_client_new(client) < 0) {
|
||||
return -1;
|
||||
@@ -386,19 +388,19 @@ int recovery_send_applelogo(struct idevicerestore_client_t* client, plist_t buil
|
||||
}
|
||||
|
||||
if (recovery_send_component(client, build_identity, component) < 0) {
|
||||
error("ERROR: Unable to send %s to device.\n", component);
|
||||
logger(LL_ERROR, "Unable to send %s to device.\n", component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
recovery_error = irecv_send_command(client->recovery->client, "setpicture 4");
|
||||
if (recovery_error != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to set %s\n", component);
|
||||
logger(LL_ERROR, "Unable to set %s\n", component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
recovery_error = irecv_send_command(client->recovery->client, "bgcolor 0 0 0");
|
||||
if (recovery_error != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to display %s\n", component);
|
||||
logger(LL_ERROR, "Unable to display %s\n", component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -415,7 +417,7 @@ int recovery_send_loaded_by_iboot(struct idevicerestore_client_t* client, plist_
|
||||
|
||||
plist_t manifest_node = plist_dict_get_item(build_identity, "Manifest");
|
||||
if (!manifest_node || plist_get_node_type(manifest_node) != PLIST_DICT) {
|
||||
error("ERROR: Unable to find manifest node\n");
|
||||
logger(LL_ERROR, "Unable to find manifest node\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -439,9 +441,9 @@ int recovery_send_loaded_by_iboot(struct idevicerestore_client_t* client, plist_
|
||||
uint8_t b = 0;
|
||||
plist_get_bool_val(iboot_node, &b);
|
||||
if (b) {
|
||||
debug("DEBUG: %s is loaded by iBoot.\n", key);
|
||||
logger(LL_DEBUG, "%s is loaded by iBoot.\n", key);
|
||||
if (recovery_send_component_and_command(client, build_identity, key, "firmware") < 0) {
|
||||
error("ERROR: Unable to send component '%s' to device.\n", key);
|
||||
logger(LL_ERROR, "Unable to send component '%s' to device.\n", key);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
@@ -466,12 +468,12 @@ int recovery_send_ramdisk(struct idevicerestore_client_t* client, plist_t build_
|
||||
|
||||
char* value = NULL;
|
||||
irecv_getenv(client->recovery->client, "ramdisk-size", &value);
|
||||
info("ramdisk-size=%s\n", (value ? value : "(unknown)"));
|
||||
logger(LL_INFO, "ramdisk-size=%s\n", (value ? value : "(unknown)"));
|
||||
free(value);
|
||||
value = NULL;
|
||||
|
||||
if (recovery_send_component(client, build_identity, component) < 0) {
|
||||
error("ERROR: Unable to send %s to device.\n", component);
|
||||
logger(LL_ERROR, "Unable to send %s to device.\n", component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -479,7 +481,7 @@ int recovery_send_ramdisk(struct idevicerestore_client_t* client, plist_t build_
|
||||
|
||||
recovery_error = irecv_send_command(client->recovery->client, "ramdisk");
|
||||
if (recovery_error != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to execute %s\n", component);
|
||||
logger(LL_ERROR, "Unable to execute %s\n", component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -500,7 +502,7 @@ int recovery_send_kernelcache(struct idevicerestore_client_t* client, plist_t bu
|
||||
}
|
||||
|
||||
if (recovery_send_component(client, build_identity, component) < 0) {
|
||||
error("ERROR: Unable to send %s to device.\n", component);
|
||||
logger(LL_ERROR, "Unable to send %s to device.\n", component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -515,7 +517,7 @@ int recovery_send_kernelcache(struct idevicerestore_client_t* client, plist_t bu
|
||||
|
||||
recovery_error = irecv_send_command_breq(client->recovery->client, "bootx", 1);
|
||||
if (recovery_error != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to execute %s\n", component);
|
||||
logger(LL_ERROR, "Unable to execute %s\n", component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
+558
-544
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user