summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorGravatar Martin Szulecki2010-06-09 02:09:40 +0200
committerGravatar Martin Szulecki2010-06-09 02:09:40 +0200
commit7d15f1a2a74c1ea3f16d5f7cab923bc6844ba214 (patch)
tree16d052ec67678ca57d6d833c7b925d2724893f62 /tools
parente08b61eb2d9af499e3f154c6c1c37312cbd55a37 (diff)
downloadlibimobiledevice-7d15f1a2a74c1ea3f16d5f7cab923bc6844ba214.tar.gz
libimobiledevice-7d15f1a2a74c1ea3f16d5f7cab923bc6844ba214.tar.bz2
idevicebackup: Implement restore command for files and make restore work
Diffstat (limited to 'tools')
-rw-r--r--tools/idevicebackup.c154
1 files changed, 128 insertions, 26 deletions
diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c
index 0994e47..d287085 100644
--- a/tools/idevicebackup.c
+++ b/tools/idevicebackup.c
@@ -219,7 +219,7 @@ static void mobilebackup_info_update_last_backup_date(plist_t info_plist)
219 node = NULL; 219 node = NULL;
220} 220}
221 221
222static void buffer_read_from_filename(const char *filename, char **buffer, uint32_t *length) 222static void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length)
223{ 223{
224 FILE *f; 224 FILE *f;
225 uint64_t size; 225 uint64_t size;
@@ -243,10 +243,10 @@ static void buffer_read_from_filename(const char *filename, char **buffer, uint3
243 fread(*buffer, sizeof(char), size, f); 243 fread(*buffer, sizeof(char), size, f);
244 fclose(f); 244 fclose(f);
245 245
246 *length = (uint32_t)size; 246 *length = size;
247} 247}
248 248
249static void buffer_write_to_filename(const char *filename, const char *buffer, uint32_t length) 249static void buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length)
250{ 250{
251 FILE *f; 251 FILE *f;
252 252
@@ -258,7 +258,7 @@ static void buffer_write_to_filename(const char *filename, const char *buffer, u
258static int plist_read_from_filename(plist_t *plist, const char *filename) 258static int plist_read_from_filename(plist_t *plist, const char *filename)
259{ 259{
260 char *buffer = NULL; 260 char *buffer = NULL;
261 uint32_t length; 261 uint64_t length;
262 262
263 if (!filename) 263 if (!filename)
264 return 0; 264 return 0;
@@ -432,7 +432,7 @@ static int mobilebackup_delete_backup_file_by_hash(const char *backup_directory,
432{ 432{
433 int ret = 0; 433 int ret = 0;
434 gchar *path = mobilebackup_build_path(backup_directory, hash, ".mddata"); 434 gchar *path = mobilebackup_build_path(backup_directory, hash, ".mddata");
435 printf("Removing \"%s\"... ", path); 435 printf("Removing \"%s\" ", path);
436 if (!remove( path )) 436 if (!remove( path ))
437 ret = 1; 437 ret = 1;
438 else 438 else
@@ -444,7 +444,7 @@ static int mobilebackup_delete_backup_file_by_hash(const char *backup_directory,
444 return ret; 444 return ret;
445 445
446 path = mobilebackup_build_path(backup_directory, hash, ".mdinfo"); 446 path = mobilebackup_build_path(backup_directory, hash, ".mdinfo");
447 printf("Removing \"%s\"... ", path); 447 printf("and \"%s\"... ", path);
448 if (!remove( path )) 448 if (!remove( path ))
449 ret = 1; 449 ret = 1;
450 else 450 else
@@ -670,9 +670,10 @@ int main(int argc, char *argv[])
670 plist_t manifest_plist = NULL; 670 plist_t manifest_plist = NULL;
671 plist_t info_plist = NULL; 671 plist_t info_plist = NULL;
672 char *buffer = NULL; 672 char *buffer = NULL;
673 char *file_path = NULL;
673 uint64_t length = 0; 674 uint64_t length = 0;
674 uint64_t backup_total_size = 0; 675 uint64_t backup_total_size = 0;
675 enum device_link_file_status_t file_status; 676 enum device_link_file_status_t file_status = DEVICE_LINK_FILE_STATUS_NONE;
676 uint64_t c = 0; 677 uint64_t c = 0;
677 678
678 /* we need to exit cleanly on running backups and restores or we cause havok */ 679 /* we need to exit cleanly on running backups and restores or we cause havok */
@@ -934,7 +935,6 @@ int main(int argc, char *argv[])
934 int file_index = 0; 935 int file_index = 0;
935 int hunk_index = 0; 936 int hunk_index = 0;
936 uint64_t backup_real_size = 0; 937 uint64_t backup_real_size = 0;
937 char *file_path = NULL;
938 char *file_ext = NULL; 938 char *file_ext = NULL;
939 char *filename_mdinfo = NULL; 939 char *filename_mdinfo = NULL;
940 char *filename_mddata = NULL; 940 char *filename_mddata = NULL;
@@ -1212,7 +1212,7 @@ int main(int argc, char *argv[])
1212 node = NULL; 1212 node = NULL;
1213 plist_dict_next_item(files, iter, &hash, &node); 1213 plist_dict_next_item(files, iter, &hash, &node);
1214 while (node) { 1214 while (node) {
1215 printf("Verifying files %d/%d (%d%%) \r", cur_file, total_files, (cur_file*100/total_files)); 1215 printf("Verifying file %d/%d (%d%%) \r", cur_file, total_files, (cur_file*100/total_files));
1216 cur_file++; 1216 cur_file++;
1217 /* make sure both .mddata/.mdinfo files are available for each entry */ 1217 /* make sure both .mddata/.mdinfo files are available for each entry */
1218 file_ok = mobilebackup_check_file_integrity(backup_directory, hash, node); 1218 file_ok = mobilebackup_check_file_integrity(backup_directory, hash, node);
@@ -1233,6 +1233,9 @@ int main(int argc, char *argv[])
1233 printf("All backup files appear to be valid\n"); 1233 printf("All backup files appear to be valid\n");
1234 } 1234 }
1235 } 1235 }
1236
1237 printf("Requesting restore from device...\n");
1238
1236 /* request restore from device with manifest (BackupMessageRestoreMigrate) */ 1239 /* request restore from device with manifest (BackupMessageRestoreMigrate) */
1237 int restore_flags = MB_RESTORE_NOTIFY_SPRINGBOARD | MB_RESTORE_PRESERVE_SETTINGS | MB_RESTORE_PRESERVE_CAMERA_ROLL; 1240 int restore_flags = MB_RESTORE_NOTIFY_SPRINGBOARD | MB_RESTORE_PRESERVE_SETTINGS | MB_RESTORE_PRESERVE_CAMERA_ROLL;
1238 err = mobilebackup_request_restore(mobilebackup, manifest_plist, restore_flags, "1.6"); 1241 err = mobilebackup_request_restore(mobilebackup, manifest_plist, restore_flags, "1.6");
@@ -1248,38 +1251,129 @@ int main(int argc, char *argv[])
1248 break; 1251 break;
1249 } 1252 }
1250 1253
1254 printf("Entered restore mode.\n");
1255
1256 int restore_ok = 0;
1257
1251 if (files && (plist_get_node_type(files) == PLIST_DICT)) { 1258 if (files && (plist_get_node_type(files) == PLIST_DICT)) {
1252 plist_dict_iter iter = NULL; 1259 plist_dict_iter iter = NULL;
1253 plist_dict_new_iter(files, &iter); 1260 plist_dict_new_iter(files, &iter);
1254 if (iter) { 1261 if (iter) {
1255 /* loop over Files entries in Manifest data plist */ 1262 /* loop over Files entries in Manifest data plist */
1256 char *hash = NULL; 1263 char *hash = NULL;
1257 int file_ok = 0; 1264 plist_t file_info = NULL;
1265 char *file_info_path = NULL;
1258 int total_files = plist_dict_get_size(files); 1266 int total_files = plist_dict_get_size(files);
1259 int cur_file = 1; 1267 int cur_file = 0;
1268 uint64_t file_offset = 0;
1269 uint8_t is_encrypted = 0;
1270 plist_t tmp_node = NULL;
1271 plist_t file_path_node = NULL;
1272 plist_t send_file_node = NULL;
1260 node = NULL; 1273 node = NULL;
1261 plist_dict_next_item(files, iter, &hash, &node); 1274 plist_dict_next_item(files, iter, &hash, &node);
1262 while (node) { 1275 while (node) {
1263 printf("Sending files %d/%d (%d%%) \r", cur_file, total_files, (cur_file*100/total_files));
1264 cur_file++;
1265
1266 /* TODO: read mddata/mdinfo files and send to device using DLSendFile */ 1276 /* TODO: read mddata/mdinfo files and send to device using DLSendFile */
1267 /* TODO: if all hunks of a file are sent, device must send ack */ 1277 file_info_path = mobilebackup_build_path(backup_directory, hash, ".mdinfo");
1268 /* err = mobilebackup_receive_restore_file_received(mobilebackup, &result); */ 1278 plist_read_from_filename(&file_info, file_info_path);
1269 node = NULL; 1279
1280 /* get encryption state */
1281 tmp_node = plist_dict_get_item(file_info, "IsEncrypted");
1282 plist_get_bool_val(tmp_node, &is_encrypted);
1283 tmp_node = NULL;
1284
1285 /* get real file path from metadata */
1286 tmp_node = plist_dict_get_item(file_info, "Metadata");
1287 plist_get_data_val(tmp_node, &buffer, &length);
1288 tmp_node = NULL;
1289 plist_from_bin(buffer, length, &tmp_node);
1290 file_path_node = plist_dict_get_item(tmp_node, "Path");
1291 plist_get_string_val(file_path_node, &file_path);
1292
1293 printf("Sending file %s %d/%d (%d%%)... ", file_path, cur_file, total_files, (cur_file*100/total_files));
1294
1295 /* add additional device link file information keys */
1296 plist_dict_insert_item(file_info, "DLFileAttributesKey", plist_copy(node));
1297 plist_dict_insert_item(file_info, "DLFileSource", plist_new_string(file_info_path));
1298 plist_dict_insert_item(file_info, "DLFileDest", plist_new_string("/tmp/RestoreFile.plist"));
1299 plist_dict_insert_item(file_info, "DLFileIsEncrypted", plist_new_bool(is_encrypted));
1300 plist_dict_insert_item(file_info, "DLFileOffsetKey", plist_new_uint(file_offset));
1301 plist_dict_insert_item(file_info, "DLFileStatusKey", plist_new_uint(file_status));
1302
1303 /* read data from file */
1304 free(file_info_path);
1305 file_info_path = mobilebackup_build_path(backup_directory, hash, ".mddata");
1306 buffer_read_from_filename(file_info_path, &buffer, &length);
1307 free(file_info_path);
1308
1309 /* send DLSendFile messages */
1310 file_offset = 0;
1311 do {
1312 if ((length-file_offset) <= 8192)
1313 file_status = DEVICE_LINK_FILE_STATUS_LAST_HUNK;
1314 else
1315 file_status = DEVICE_LINK_FILE_STATUS_HUNK;
1316
1317 plist_dict_remove_item(file_info, "DLFileOffsetKey");
1318 plist_dict_insert_item(file_info, "DLFileOffsetKey", plist_new_uint(file_offset));
1319
1320 plist_dict_remove_item(file_info, "DLFileStatusKey");
1321 plist_dict_insert_item(file_info, "DLFileStatusKey", plist_new_uint(file_status));
1322
1323 send_file_node = plist_new_array();
1324
1325 plist_array_append_item(send_file_node, plist_new_string("DLSendFile"));
1326
1327 if (file_status == DEVICE_LINK_FILE_STATUS_LAST_HUNK)
1328 plist_array_append_item(send_file_node, plist_new_data(buffer+file_offset, length-file_offset));
1329 else
1330 plist_array_append_item(send_file_node, plist_new_data(buffer+file_offset, 8192));
1331
1332 plist_array_append_item(send_file_node, plist_copy(file_info));
1333
1334 err = mobilebackup_send(mobilebackup, send_file_node);
1335 if (err != MOBILEBACKUP_E_SUCCESS) {
1336 printf("ERROR: Unable to send file hunk due to error %d. Aborting...\n", err);
1337 file_status = DEVICE_LINK_FILE_STATUS_NONE;
1338 }
1339
1340 if (file_status == DEVICE_LINK_FILE_STATUS_LAST_HUNK) {
1341 /* TODO: if all hunks of a file are sent, device must send ack */
1342 err = mobilebackup_receive_restore_file_received(mobilebackup, NULL);
1343 if (err != MOBILEBACKUP_E_SUCCESS) {
1344 printf("ERROR: Did not receive an ack for the sent file due to error %d. Aborting...\n", err);
1345 file_status = DEVICE_LINK_FILE_STATUS_NONE;
1346 }
1347 }
1348
1349 file_offset += 8192;
1350
1351 if (file_status == DEVICE_LINK_FILE_STATUS_LAST_HUNK)
1352 printf("DONE\n");
1353
1354 plist_free(send_file_node);
1355
1356 if (file_status == DEVICE_LINK_FILE_STATUS_NONE)
1357 break;
1358
1359 } while((file_offset < length));
1360
1270 free(hash); 1361 free(hash);
1362 node = NULL;
1271 hash = NULL; 1363 hash = NULL;
1272 if (!file_ok) { 1364
1365 restore_ok = 1;
1366 if (file_status == DEVICE_LINK_FILE_STATUS_NONE) {
1367 restore_ok = 0;
1273 break; 1368 break;
1274 } 1369 }
1370
1371 cur_file++;
1275 plist_dict_next_item(files, iter, &hash, &node); 1372 plist_dict_next_item(files, iter, &hash, &node);
1276 } 1373 }
1277 printf("\n");
1278 free(iter); 1374 free(iter);
1279 if (!file_ok) { 1375
1280 plist_free(backup_data); 1376 printf("Restored %d files on device.\n", cur_file);
1281 break;
1282 }
1283 } 1377 }
1284 } 1378 }
1285 /* TODO: observe notification_proxy id com.apple.mobile.application_installed */ 1379 /* TODO: observe notification_proxy id com.apple.mobile.application_installed */
@@ -1290,9 +1384,17 @@ int main(int argc, char *argv[])
1290 plist_free(backup_data); 1384 plist_free(backup_data);
1291 1385
1292 /* signal restore finished message to device; BackupMessageRestoreComplete */ 1386 /* signal restore finished message to device; BackupMessageRestoreComplete */
1293 err = mobilebackup_send_restore_complete(mobilebackup); 1387 if (restore_ok) {
1294 if (err != MOBILEBACKUP_E_SUCCESS) { 1388 err = mobilebackup_send_restore_complete(mobilebackup);
1295 printf("ERROR: Could not send BackupMessageRestoreComplete, error code %d\n", err); 1389 if (err != MOBILEBACKUP_E_SUCCESS) {
1390 printf("ERROR: Could not send BackupMessageRestoreComplete, error code %d\n", err);
1391 }
1392 }
1393
1394 if (restore_ok) {
1395 printf("Restore Successful.\n");
1396 } else {
1397 printf("Restore Failed.\n");
1296 } 1398 }
1297 break; 1399 break;
1298 case CMD_LEAVE: 1400 case CMD_LEAVE: