diff options
| author | 2010-11-27 20:47:24 +0100 | |
|---|---|---|
| committer | 2011-04-11 19:42:18 +0200 | |
| commit | 5eefa4828535a905f9af5fd7ea0ad00b2f955103 (patch) | |
| tree | 31ee2bbe24f463c814e5741a3af81c1a3bc79f1e /tools | |
| parent | 88bdba29da9faab1520881d8f7b6929baeb109ae (diff) | |
| download | libimobiledevice-5eefa4828535a905f9af5fd7ea0ad00b2f955103.tar.gz libimobiledevice-5eefa4828535a905f9af5fd7ea0ad00b2f955103.tar.bz2 | |
idevicebackup4: create (mostly) proper Info.plist
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/idevicebackup4.c | 155 |
1 files changed, 135 insertions, 20 deletions
diff --git a/tools/idevicebackup4.c b/tools/idevicebackup4.c index c682e76..c2e067d 100644 --- a/tools/idevicebackup4.c +++ b/tools/idevicebackup4.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | 47 | ||
| 48 | static mobilebackup2_client_t mobilebackup2 = NULL; | 48 | static mobilebackup2_client_t mobilebackup2 = NULL; |
| 49 | static lockdownd_client_t client = NULL; | 49 | static lockdownd_client_t client = NULL; |
| 50 | static afc_client_t afc = NULL; | ||
| 50 | static idevice_t phone = NULL; | 51 | static idevice_t phone = NULL; |
| 51 | 52 | ||
| 52 | static int quit_flag = 0; | 53 | static int quit_flag = 0; |
| @@ -70,6 +71,7 @@ enum device_link_file_status_t { | |||
| 70 | DEVICE_LINK_FILE_STATUS_LAST_HUNK | 71 | DEVICE_LINK_FILE_STATUS_LAST_HUNK |
| 71 | }; | 72 | }; |
| 72 | 73 | ||
| 74 | #if 0 | ||
| 73 | static void sha1_of_data(const char *input, uint32_t size, unsigned char *hash_out) | 75 | static void sha1_of_data(const char *input, uint32_t size, unsigned char *hash_out) |
| 74 | { | 76 | { |
| 75 | gcry_md_hash_buffer(GCRY_MD_SHA1, hash_out, input, size); | 77 | gcry_md_hash_buffer(GCRY_MD_SHA1, hash_out, input, size); |
| @@ -142,6 +144,7 @@ static void print_hash(const unsigned char *hash, int len) | |||
| 142 | printf("%02x", hash[i]); | 144 | printf("%02x", hash[i]); |
| 143 | } | 145 | } |
| 144 | } | 146 | } |
| 147 | #endif | ||
| 145 | 148 | ||
| 146 | static void notify_cb(const char *notification, void *userdata) | 149 | static void notify_cb(const char *notification, void *userdata) |
| 147 | { | 150 | { |
| @@ -184,6 +187,71 @@ static void debug_buf(const char *data, const int length) | |||
| 184 | fprintf(stdout, "\n"); | 187 | fprintf(stdout, "\n"); |
| 185 | } | 188 | } |
| 186 | 189 | ||
| 190 | static void free_dictionary(char **dictionary) | ||
| 191 | { | ||
| 192 | int i = 0; | ||
| 193 | |||
| 194 | if (!dictionary) | ||
| 195 | return; | ||
| 196 | |||
| 197 | for (i = 0; dictionary[i]; i++) { | ||
| 198 | free(dictionary[i]); | ||
| 199 | } | ||
| 200 | free(dictionary); | ||
| 201 | } | ||
| 202 | |||
| 203 | static void mobilebackup_afc_get_file_contents(const char *filename, char **data, uint64_t *size) | ||
| 204 | { | ||
| 205 | if (!afc || !data || !size) { | ||
| 206 | return; | ||
| 207 | } | ||
| 208 | |||
| 209 | char **fileinfo; | ||
| 210 | uint32_t fsize = 0; | ||
| 211 | |||
| 212 | afc_get_file_info(afc, filename, &fileinfo); | ||
| 213 | if (!fileinfo) { | ||
| 214 | return; | ||
| 215 | } | ||
| 216 | int i; | ||
| 217 | for (i = 0; fileinfo[i]; i+=2) { | ||
| 218 | if (!strcmp(fileinfo[i], "st_size")) { | ||
| 219 | fsize = atol(fileinfo[i+1]); | ||
| 220 | break; | ||
| 221 | } | ||
| 222 | } | ||
| 223 | free_dictionary(fileinfo); | ||
| 224 | |||
| 225 | if (fsize == 0) { | ||
| 226 | return; | ||
| 227 | } | ||
| 228 | |||
| 229 | uint64_t f = 0; | ||
| 230 | afc_file_open(afc, filename, AFC_FOPEN_RDONLY, &f); | ||
| 231 | if (!f) { | ||
| 232 | return; | ||
| 233 | } | ||
| 234 | char *buf = (char*)malloc((uint32_t)fsize); | ||
| 235 | uint32_t done = 0; | ||
| 236 | while (done < fsize) { | ||
| 237 | uint32_t bread = 0; | ||
| 238 | afc_file_read(afc, f, buf+done, 65536, &bread); | ||
| 239 | if (bread > 0) { | ||
| 240 | |||
| 241 | } else { | ||
| 242 | break; | ||
| 243 | } | ||
| 244 | done += bread; | ||
| 245 | } | ||
| 246 | if (done == fsize) { | ||
| 247 | *size = fsize; | ||
| 248 | *data = buf; | ||
| 249 | } else { | ||
| 250 | free(buf); | ||
| 251 | } | ||
| 252 | afc_file_close(afc, f); | ||
| 253 | } | ||
| 254 | |||
| 187 | static plist_t mobilebackup_factory_info_plist_new() | 255 | static plist_t mobilebackup_factory_info_plist_new() |
| 188 | { | 256 | { |
| 189 | /* gather data from lockdown */ | 257 | /* gather data from lockdown */ |
| @@ -209,6 +277,10 @@ static plist_t mobilebackup_factory_info_plist_new() | |||
| 209 | /* FIXME: How is the GUID generated? */ | 277 | /* FIXME: How is the GUID generated? */ |
| 210 | plist_dict_insert_item(ret, "GUID", plist_new_string("---")); | 278 | plist_dict_insert_item(ret, "GUID", plist_new_string("---")); |
| 211 | 279 | ||
| 280 | value_node = plist_dict_get_item(root_node, "IntegratedCircuitCardIdentity"); | ||
| 281 | if (value_node) | ||
| 282 | plist_dict_insert_item(ret, "ICCID", plist_copy(value_node)); | ||
| 283 | |||
| 212 | value_node = plist_dict_get_item(root_node, "InternationalMobileEquipmentIdentity"); | 284 | value_node = plist_dict_get_item(root_node, "InternationalMobileEquipmentIdentity"); |
| 213 | if (value_node) | 285 | if (value_node) |
| 214 | plist_dict_insert_item(ret, "IMEI", plist_copy(value_node)); | 286 | plist_dict_insert_item(ret, "IMEI", plist_copy(value_node)); |
| @@ -216,6 +288,9 @@ static plist_t mobilebackup_factory_info_plist_new() | |||
| 216 | g_get_current_time(&tv); | 288 | g_get_current_time(&tv); |
| 217 | plist_dict_insert_item(ret, "Last Backup Date", plist_new_date(tv.tv_sec, tv.tv_usec)); | 289 | plist_dict_insert_item(ret, "Last Backup Date", plist_new_date(tv.tv_sec, tv.tv_usec)); |
| 218 | 290 | ||
| 291 | value_node = plist_dict_get_item(root_node, "PhoneNumber"); | ||
| 292 | plist_dict_insert_item(ret, "Phone Number", plist_copy(value_node)); | ||
| 293 | |||
| 219 | value_node = plist_dict_get_item(root_node, "ProductType"); | 294 | value_node = plist_dict_get_item(root_node, "ProductType"); |
| 220 | plist_dict_insert_item(ret, "Product Type", plist_copy(value_node)); | 295 | plist_dict_insert_item(ret, "Product Type", plist_copy(value_node)); |
| 221 | 296 | ||
| @@ -225,26 +300,68 @@ static plist_t mobilebackup_factory_info_plist_new() | |||
| 225 | value_node = plist_dict_get_item(root_node, "SerialNumber"); | 300 | value_node = plist_dict_get_item(root_node, "SerialNumber"); |
| 226 | plist_dict_insert_item(ret, "Serial Number", plist_copy(value_node)); | 301 | plist_dict_insert_item(ret, "Serial Number", plist_copy(value_node)); |
| 227 | 302 | ||
| 303 | /* FIXME Sync Settings? */ | ||
| 304 | |||
| 228 | value_node = plist_dict_get_item(root_node, "UniqueDeviceID"); | 305 | value_node = plist_dict_get_item(root_node, "UniqueDeviceID"); |
| 229 | idevice_get_uuid(phone, &uuid); | 306 | idevice_get_uuid(phone, &uuid); |
| 230 | plist_dict_insert_item(ret, "Target Identifier", plist_new_string(uuid)); | 307 | plist_dict_insert_item(ret, "Target Identifier", plist_new_string(uuid)); |
| 231 | 308 | ||
| 309 | plist_dict_insert_item(ret, "Target Type", plist_new_string("Device")); | ||
| 310 | |||
| 232 | /* uppercase */ | 311 | /* uppercase */ |
| 233 | uuid_uppercase = g_ascii_strup(uuid, -1); | 312 | uuid_uppercase = g_ascii_strup(uuid, -1); |
| 234 | plist_dict_insert_item(ret, "Unique Identifier", plist_new_string(uuid_uppercase)); | 313 | plist_dict_insert_item(ret, "Unique Identifier", plist_new_string(uuid_uppercase)); |
| 235 | free(uuid_uppercase); | 314 | free(uuid_uppercase); |
| 236 | free(uuid); | 315 | free(uuid); |
| 237 | 316 | ||
| 238 | /* FIXME: Embed files as <data> nodes */ | 317 | char *data_buf = NULL; |
| 318 | uint64_t data_size = 0; | ||
| 319 | mobilebackup_afc_get_file_contents("/Books/iBooksData2.plist", &data_buf, &data_size); | ||
| 320 | if (data_buf) { | ||
| 321 | plist_dict_insert_item(ret, "iBooks Data 2", plist_new_data(data_buf, data_size)); | ||
| 322 | free(data_buf); | ||
| 323 | } | ||
| 324 | |||
| 239 | plist_t files = plist_new_dict(); | 325 | plist_t files = plist_new_dict(); |
| 326 | const char *itunesfiles[] = { | ||
| 327 | "ApertureAlbumPrefs", | ||
| 328 | "IC-Info.sidb", | ||
| 329 | "IC-Info.sidv", | ||
| 330 | "PhotosFolderAlbums", | ||
| 331 | "PhotosFolderName", | ||
| 332 | "PhotosFolderPrefs", | ||
| 333 | "iPhotoAlbumPrefs", | ||
| 334 | "iTunesApplicationIDs", | ||
| 335 | "iTunesPrefs", | ||
| 336 | "iTunesPrefs.plist", | ||
| 337 | NULL | ||
| 338 | }; | ||
| 339 | int i = 0; | ||
| 340 | for (i = 0; itunesfiles[i]; i++) { | ||
| 341 | data_buf = NULL; | ||
| 342 | data_size = 0; | ||
| 343 | gchar *fname = g_strconcat("/iTunes_Control/iTunes/", itunesfiles[i], NULL); | ||
| 344 | mobilebackup_afc_get_file_contents(fname, &data_buf, &data_size); | ||
| 345 | g_free(fname); | ||
| 346 | if (data_buf) { | ||
| 347 | plist_dict_insert_item(files, itunesfiles[i], plist_new_data(data_buf, data_size)); | ||
| 348 | free(data_buf); | ||
| 349 | } | ||
| 350 | } | ||
| 240 | plist_dict_insert_item(ret, "iTunes Files", files); | 351 | plist_dict_insert_item(ret, "iTunes Files", files); |
| 241 | plist_dict_insert_item(ret, "iTunes Version", plist_new_string("9.0.2")); | 352 | |
| 353 | plist_t itunes_settings = plist_new_dict(); | ||
| 354 | lockdownd_get_value(client, "com.apple.iTunes", NULL, &itunes_settings); | ||
| 355 | plist_dict_insert_item(ret, "iTunes Settings", itunes_settings); | ||
| 356 | |||
| 357 | plist_dict_insert_item(ret, "iTunes Version", plist_new_string("10.0.1")); | ||
| 242 | 358 | ||
| 243 | plist_free(root_node); | 359 | plist_free(root_node); |
| 244 | 360 | ||
| 245 | return ret; | 361 | return ret; |
| 246 | } | 362 | } |
| 247 | 363 | ||
| 364 | #if 0 | ||
| 248 | static void mobilebackup_info_update_last_backup_date(plist_t info_plist) | 365 | static void mobilebackup_info_update_last_backup_date(plist_t info_plist) |
| 249 | { | 366 | { |
| 250 | GTimeVal tv = {0, 0}; | 367 | GTimeVal tv = {0, 0}; |
| @@ -259,6 +376,7 @@ static void mobilebackup_info_update_last_backup_date(plist_t info_plist) | |||
| 259 | 376 | ||
| 260 | node = NULL; | 377 | node = NULL; |
| 261 | } | 378 | } |
| 379 | #endif | ||
| 262 | 380 | ||
| 263 | static void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length) | 381 | static void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length) |
| 264 | { | 382 | { |
| @@ -505,6 +623,7 @@ static int mobilebackup_info_is_current_device(plist_t info) | |||
| 505 | return ret; | 623 | return ret; |
| 506 | }*/ | 624 | }*/ |
| 507 | 625 | ||
| 626 | #if 0 | ||
| 508 | static int mobilebackup_check_file_integrity(const char *backup_directory, const char *hash, plist_t filedata) | 627 | static int mobilebackup_check_file_integrity(const char *backup_directory, const char *hash, plist_t filedata) |
| 509 | { | 628 | { |
| 510 | char *datapath; | 629 | char *datapath; |
| @@ -655,6 +774,7 @@ static int mobilebackup_check_file_integrity(const char *backup_directory, const | |||
| 655 | plist_free(mdinfo); | 774 | plist_free(mdinfo); |
| 656 | return res; | 775 | return res; |
| 657 | } | 776 | } |
| 777 | #endif | ||
| 658 | 778 | ||
| 659 | static void do_post_notification(const char *notification) | 779 | static void do_post_notification(const char *notification) |
| 660 | { | 780 | { |
| @@ -1204,8 +1324,6 @@ int main(int argc, char *argv[]) | |||
| 1204 | printf("ERROR: Backup directory \"%s\" is invalid. No Info.plist found.\n", backup_directory); | 1324 | printf("ERROR: Backup directory \"%s\" is invalid. No Info.plist found.\n", backup_directory); |
| 1205 | return -1; | 1325 | return -1; |
| 1206 | } | 1326 | } |
| 1207 | } else if (cmd == CMD_BACKUP) { | ||
| 1208 | is_full_backup = 1; | ||
| 1209 | } | 1327 | } |
| 1210 | 1328 | ||
| 1211 | printf("Backup directory is \"%s\"\n", backup_directory); | 1329 | printf("Backup directory is \"%s\"\n", backup_directory); |
| @@ -1233,7 +1351,7 @@ int main(int argc, char *argv[]) | |||
| 1233 | printf("ERROR: Could not start service %s.\n", NP_SERVICE_NAME); | 1351 | printf("ERROR: Could not start service %s.\n", NP_SERVICE_NAME); |
| 1234 | } | 1352 | } |
| 1235 | 1353 | ||
| 1236 | afc_client_t afc = NULL; | 1354 | afc = NULL; |
| 1237 | if (cmd == CMD_BACKUP) { | 1355 | if (cmd == CMD_BACKUP) { |
| 1238 | /* start AFC, we need this for the lock file */ | 1356 | /* start AFC, we need this for the lock file */ |
| 1239 | port = 0; | 1357 | port = 0; |
| @@ -1277,9 +1395,9 @@ int main(int argc, char *argv[]) | |||
| 1277 | if (info_plist && (cmd == CMD_BACKUP)) { | 1395 | if (info_plist && (cmd == CMD_BACKUP)) { |
| 1278 | if (mobilebackup_info_is_current_device(info_plist)) { | 1396 | if (mobilebackup_info_is_current_device(info_plist)) { |
| 1279 | /* update the last backup time within Info.plist */ | 1397 | /* update the last backup time within Info.plist */ |
| 1280 | mobilebackup_info_update_last_backup_date(info_plist); | 1398 | //mobilebackup_info_update_last_backup_date(info_plist); |
| 1281 | remove(info_path); | 1399 | //remove(info_path); |
| 1282 | plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); | 1400 | //plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); |
| 1283 | } else { | 1401 | } else { |
| 1284 | printf("Aborting backup. Backup is not compatible with the current device.\n"); | 1402 | printf("Aborting backup. Backup is not compatible with the current device.\n"); |
| 1285 | cmd = CMD_LEAVE; | 1403 | cmd = CMD_LEAVE; |
| @@ -1361,17 +1479,14 @@ checkpoint: | |||
| 1361 | 1479 | ||
| 1362 | /* Info.plist (Device infos, IC-Info.sidb, photos, app_ids, iTunesPrefs) */ | 1480 | /* Info.plist (Device infos, IC-Info.sidb, photos, app_ids, iTunesPrefs) */ |
| 1363 | 1481 | ||
| 1364 | /* create new Info.plist on new backups */ | 1482 | /* re-create Info.plist */ |
| 1365 | if (is_full_backup) { | 1483 | if (info_plist) { |
| 1366 | if (info_plist) { | 1484 | plist_free(info_plist); |
| 1367 | plist_free(info_plist); | 1485 | info_plist = NULL; |
| 1368 | info_plist = NULL; | ||
| 1369 | } | ||
| 1370 | remove(info_path); | ||
| 1371 | printf("Creating Info.plist for new backup.\n"); | ||
| 1372 | info_plist = mobilebackup_factory_info_plist_new(); | ||
| 1373 | plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); | ||
| 1374 | } | 1486 | } |
| 1487 | info_plist = mobilebackup_factory_info_plist_new(); | ||
| 1488 | remove(info_path); | ||
| 1489 | plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); | ||
| 1375 | g_free(info_path); | 1490 | g_free(info_path); |
| 1376 | 1491 | ||
| 1377 | plist_free(info_plist); | 1492 | plist_free(info_plist); |
| @@ -1385,10 +1500,10 @@ checkpoint: | |||
| 1385 | 1500 | ||
| 1386 | err = mobilebackup2_send_request(mobilebackup2, "Backup", uuid, NULL, NULL); | 1501 | err = mobilebackup2_send_request(mobilebackup2, "Backup", uuid, NULL, NULL); |
| 1387 | if (err == MOBILEBACKUP2_E_SUCCESS) { | 1502 | if (err == MOBILEBACKUP2_E_SUCCESS) { |
| 1388 | /*if (is_full_backup) | 1503 | if (is_full_backup) |
| 1389 | printf("Full backup mode.\n"); | 1504 | printf("Full backup mode.\n"); |
| 1390 | else | 1505 | else |
| 1391 | printf("Incremental backup mode.\n");*/ | 1506 | printf("Incremental backup mode.\n"); |
| 1392 | //printf("Please wait. Device is preparing backup data...\n"); | 1507 | //printf("Please wait. Device is preparing backup data...\n"); |
| 1393 | } else { | 1508 | } else { |
| 1394 | if (err == MOBILEBACKUP2_E_BAD_VERSION) { | 1509 | if (err == MOBILEBACKUP2_E_BAD_VERSION) { |
