summaryrefslogtreecommitdiffstats
path: root/tools/idevicebackup.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/idevicebackup.c')
-rw-r--r--tools/idevicebackup.c152
1 files changed, 83 insertions, 69 deletions
diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c
index 1e512d8..0affd7a 100644
--- a/tools/idevicebackup.c
+++ b/tools/idevicebackup.c
@@ -31,6 +31,7 @@
31#include <errno.h> 31#include <errno.h>
32#include <stdlib.h> 32#include <stdlib.h>
33#include <signal.h> 33#include <signal.h>
34#include <getopt.h>
34#if defined(HAVE_OPENSSL) 35#if defined(HAVE_OPENSSL)
35#include <openssl/sha.h> 36#include <openssl/sha.h>
36#elif defined(HAVE_GNUTLS) 37#elif defined(HAVE_GNUTLS)
@@ -647,27 +648,28 @@ static void clean_exit(int sig)
647 quit_flag++; 648 quit_flag++;
648} 649}
649 650
650static void print_usage(int argc, char **argv) 651static void print_usage(int argc, char **argv, int is_error)
651{ 652{
652 char *name = NULL; 653 char *name = strrchr(argv[0], '/');
653 name = strrchr(argv[0], '/'); 654 fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] CMD DIRECTORY\n", (name ? name + 1: argv[0]));
654 printf("Usage: %s [OPTIONS] CMD [DIRECTORY]\n", (name ? name + 1: argv[0])); 655 fprintf(is_error ? stderr : stdout,
655 printf("\n"); 656 "\n"
656 printf("Create or restore backup from the current or specified directory.\n"); 657 "Create or restore backup in/from the specified directory.\n"
657 printf("\n"); 658 "\n"
658 printf("CMD:\n"); 659 "CMD:\n"
659 printf(" backup\tSaves a device backup into DIRECTORY\n"); 660 " backup Saves a device backup into DIRECTORY\n"
660 printf(" restore\tRestores a device backup from DIRECTORY.\n"); 661 " restore Restores a device backup from DIRECTORY.\n"
661 printf("\n"); 662 "\n"
662 printf("OPTIONS:\n"); 663 "OPTIONS:\n"
663 printf(" -u, --udid UDID\ttarget specific device by UDID\n"); 664 " -u, --udid UDID target specific device by UDID\n"
664 printf(" -n, --network\t\tconnect to network device\n"); 665 " -n, --network connect to network device\n"
665 printf(" -d, --debug\t\tenable communication debugging\n"); 666 " -d, --debug enable communication debugging\n"
666 printf(" -h, --help\t\tprints usage information\n"); 667 " -h, --help prints usage information\n"
667 printf(" -v, --version\t\tprints version information\n"); 668 " -v, --version prints version information\n"
668 printf("\n"); 669 "\n"
669 printf("Homepage: <" PACKAGE_URL ">\n"); 670 "Homepage: <" PACKAGE_URL ">\n"
670 printf("Bug Reports: <" PACKAGE_BUGREPORT ">\n"); 671 "Bug Reports: <" PACKAGE_BUGREPORT ">\n"
672 );
671} 673}
672 674
673int main(int argc, char *argv[]) 675int main(int argc, char *argv[])
@@ -691,7 +693,15 @@ int main(int argc, char *argv[])
691 uint64_t length = 0; 693 uint64_t length = 0;
692 uint64_t backup_total_size = 0; 694 uint64_t backup_total_size = 0;
693 enum device_link_file_status_t file_status = DEVICE_LINK_FILE_STATUS_NONE; 695 enum device_link_file_status_t file_status = DEVICE_LINK_FILE_STATUS_NONE;
694 uint64_t c = 0; 696 int c = 0;
697 const struct option longopts[] = {
698 { "debug", no_argument, NULL, 'd' },
699 { "help", no_argument, NULL, 'h' },
700 { "udid", required_argument, NULL, 'u' },
701 { "network", no_argument, NULL, 'n' },
702 { "version", no_argument, NULL, 'v' },
703 { NULL, 0, NULL, 0}
704 };
695 705
696 /* we need to exit cleanly on running backups and restores or we cause havok */ 706 /* we need to exit cleanly on running backups and restores or we cause havok */
697 signal(SIGINT, clean_exit); 707 signal(SIGINT, clean_exit);
@@ -702,59 +712,58 @@ int main(int argc, char *argv[])
702#endif 712#endif
703 713
704 /* parse cmdline args */ 714 /* parse cmdline args */
705 for (i = 1; i < argc; i++) { 715 while ((c = getopt_long(argc, argv, "dhu:nv", longopts, NULL)) != -1) {
706 if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { 716 switch (c) {
717 case 'd':
707 idevice_set_debug_level(1); 718 idevice_set_debug_level(1);
708 continue; 719 break;
709 } 720 case 'u':
710 else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { 721 if (!*optarg) {
711 i++; 722 fprintf(stderr, "ERROR: UDID must not be empty!\n");
712 if (!argv[i] || !*argv[i]) { 723 print_usage(argc, argv, 1);
713 print_usage(argc, argv); 724 return 2;
714 return 0;
715 } 725 }
716 udid = strdup(argv[i]); 726 udid = strdup(optarg);
717 continue; 727 break;
718 } 728 case 'n':
719 else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--network")) {
720 use_network = 1; 729 use_network = 1;
721 continue; 730 break;
722 } 731 case 'h':
723 else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { 732 print_usage(argc, argv, 0);
724 print_usage(argc, argv);
725 return 0; 733 return 0;
726 } 734 case 'v':
727 else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
728 printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION); 735 printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION);
729 return 0; 736 return 0;
730 } 737 default:
731 else if (!strcmp(argv[i], "backup")) { 738 print_usage(argc, argv, 1);
732 cmd = CMD_BACKUP; 739 return 2;
733 }
734 else if (!strcmp(argv[i], "restore")) {
735 cmd = CMD_RESTORE;
736 }
737 else if (backup_directory == NULL) {
738 backup_directory = argv[i];
739 }
740 else {
741 print_usage(argc, argv);
742 return 0;
743 } 740 }
744 } 741 }
742 argc -= optind;
743 argv += optind;
745 744
746 /* verify options */ 745 if (argc < 1) {
747 if (cmd == -1) { 746 fprintf(stderr, "ERROR: Missing command.\n");
748 printf("No command specified.\n"); 747 print_usage(argc+optind, argv-optind, 1);
749 print_usage(argc, argv); 748 return 2;
750 return -1;
751 } 749 }
752 750
753 if (backup_directory == NULL) { 751 if (!strcmp(argv[0], "backup")) {
754 printf("No target backup directory specified.\n"); 752 cmd = CMD_BACKUP;
755 print_usage(argc, argv); 753 } else if (!strcmp(argv[0], "restore")) {
756 return -1; 754 cmd = CMD_RESTORE;
755 } else {
756 fprintf(stderr, "ERROR: Invalid command '%s'.\n", argv[0]);
757 print_usage(argc+optind, argv-optind, 1);
758 return 2;
759 }
760
761 if (argc < 2) {
762 fprintf(stderr, "No target backup directory specified.\n");
763 print_usage(argc+optind, argv-optind, 1);
764 return 2;
757 } 765 }
766 backup_directory = argv[1];
758 767
759 /* verify if passed backup directory exists */ 768 /* verify if passed backup directory exists */
760 if (stat(backup_directory, &st) != 0) { 769 if (stat(backup_directory, &st) != 0) {
@@ -784,9 +793,14 @@ int main(int argc, char *argv[])
784 return -1; 793 return -1;
785 } 794 }
786 795
796 if (!udid) {
797 idevice_get_udid(device, &udid);
798 }
799
787 if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(device, &client, TOOL_NAME))) { 800 if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(device, &client, TOOL_NAME))) {
788 printf("ERROR: Could not connect to lockdownd, error code %d\n", ldret); 801 printf("ERROR: Could not connect to lockdownd, error code %d\n", ldret);
789 idevice_free(device); 802 idevice_free(device);
803 free(udid);
790 return -1; 804 return -1;
791 } 805 }
792 806
@@ -806,6 +820,7 @@ int main(int argc, char *argv[])
806 printf("ERROR: This tool is only compatible with iOS 3 or below. For newer iOS versions please use the idevicebackup2 tool.\n"); 820 printf("ERROR: This tool is only compatible with iOS 3 or below. For newer iOS versions please use the idevicebackup2 tool.\n");
807 lockdownd_client_free(client); 821 lockdownd_client_free(client);
808 idevice_free(device); 822 idevice_free(device);
823 free(udid);
809 return -1; 824 return -1;
810 } 825 }
811 } 826 }
@@ -851,7 +866,7 @@ int main(int argc, char *argv[])
851 ldret = lockdownd_start_service(client, MOBILEBACKUP_SERVICE_NAME, &service); 866 ldret = lockdownd_start_service(client, MOBILEBACKUP_SERVICE_NAME, &service);
852 if ((ldret == LOCKDOWN_E_SUCCESS) && service && service->port) { 867 if ((ldret == LOCKDOWN_E_SUCCESS) && service && service->port) {
853 printf("Started \"%s\" service on port %d.\n", MOBILEBACKUP_SERVICE_NAME, service->port); 868 printf("Started \"%s\" service on port %d.\n", MOBILEBACKUP_SERVICE_NAME, service->port);
854 mobilebackup_client_new(device, service, &mobilebackup); 869 printf("%d\n", mobilebackup_client_new(device, service, &mobilebackup));
855 870
856 if (service) { 871 if (service) {
857 lockdownd_service_descriptor_free(service); 872 lockdownd_service_descriptor_free(service);
@@ -993,7 +1008,7 @@ int main(int argc, char *argv[])
993 } else if (err == MOBILEBACKUP_E_REPLY_NOT_OK) { 1008 } else if (err == MOBILEBACKUP_E_REPLY_NOT_OK) {
994 printf("ERROR: Could not start backup process: device refused to start the backup process.\n"); 1009 printf("ERROR: Could not start backup process: device refused to start the backup process.\n");
995 } else { 1010 } else {
996 printf("ERROR: Could not start backup process: unspecified error occurred\n"); 1011 printf("ERROR: Could not start backup process: unspecified error occurred (%d)\n", err);
997 } 1012 }
998 break; 1013 break;
999 } 1014 }
@@ -1015,6 +1030,7 @@ int main(int argc, char *argv[])
1015 char *format_size = NULL; 1030 char *format_size = NULL;
1016 int is_manifest = 0; 1031 int is_manifest = 0;
1017 uint8_t b = 0; 1032 uint8_t b = 0;
1033 uint64_t u64val = 0;
1018 1034
1019 /* process series of DLSendFile messages */ 1035 /* process series of DLSendFile messages */
1020 do { 1036 do {
@@ -1046,8 +1062,8 @@ int main(int argc, char *argv[])
1046 1062
1047 /* check DLFileStatusKey (codes: 1 = Hunk, 2 = Last Hunk) */ 1063 /* check DLFileStatusKey (codes: 1 = Hunk, 2 = Last Hunk) */
1048 node = plist_dict_get_item(node_tmp, "DLFileStatusKey"); 1064 node = plist_dict_get_item(node_tmp, "DLFileStatusKey");
1049 plist_get_uint_val(node, &c); 1065 plist_get_uint_val(node, &u64val);
1050 file_status = c; 1066 file_status = u64val;
1051 1067
1052 /* get source filename */ 1068 /* get source filename */
1053 node = plist_dict_get_item(node_tmp, "BackupManifestKey"); 1069 node = plist_dict_get_item(node_tmp, "BackupManifestKey");
@@ -1610,9 +1626,7 @@ files_out:
1610 1626
1611 idevice_free(device); 1627 idevice_free(device);
1612 1628
1613 if (udid) { 1629 free(udid);
1614 free(udid);
1615 }
1616 1630
1617 return 0; 1631 return 0;
1618} 1632}