summaryrefslogtreecommitdiffstats
path: root/tools/idevicebackup2.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2022-04-30 13:31:20 +0200
committerGravatar Nikias Bassen2022-04-30 13:31:20 +0200
commit6cb13f9e6d3939930aecf91d8e23d1896a3b92e5 (patch)
tree371e4676ac914d9eef6bb4cfc0b5b6dc6f27da4f /tools/idevicebackup2.c
parent3b5cad28fabb236e05b8fff82fab5098127aa2bb (diff)
downloadlibimobiledevice-6cb13f9e6d3939930aecf91d8e23d1896a3b92e5.tar.gz
libimobiledevice-6cb13f9e6d3939930aecf91d8e23d1896a3b92e5.tar.bz2
tools: Use getopt for option parsing in all tools
Diffstat (limited to 'tools/idevicebackup2.c')
-rw-r--r--tools/idevicebackup2.c423
1 files changed, 224 insertions, 199 deletions
diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c
index 2170f98..d1ef0d6 100644
--- a/tools/idevicebackup2.c
+++ b/tools/idevicebackup2.c
@@ -36,6 +36,7 @@
#include <libgen.h>
#include <ctype.h>
#include <time.h>
+#include <getopt.h>
#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/lockdown.h>
@@ -1415,47 +1416,48 @@ static void clean_exit(int sig)
quit_flag++;
}
-static void print_usage(int argc, char **argv)
+static void print_usage(int argc, char **argv, int is_error)
{
- char *name = NULL;
- name = strrchr(argv[0], '/');
- printf("Usage: %s [OPTIONS] CMD [CMDOPTIONS] DIRECTORY\n", (name ? name + 1: argv[0]));
- printf("\n");
- printf("Create or restore backup from the current or specified directory.\n");
- printf("\n");
- printf("CMD:\n");
- printf(" backup\tcreate backup for the device\n");
- printf(" --full\t\tforce full backup from device.\n");
- printf(" restore\trestore last backup to the device\n");
- printf(" --system\t\trestore system files, too.\n");
- printf(" --no-reboot\t\tdo NOT reboot the device when done (default: yes).\n");
- printf(" --copy\t\tcreate a copy of backup folder before restoring.\n");
- printf(" --settings\t\trestore device settings from the backup.\n");
- printf(" --remove\t\tremove items which are not being restored\n");
- printf(" --skip-apps\t\tdo not trigger re-installation of apps after restore\n");
- printf(" --password PWD\tsupply the password for the encrypted source backup\n");
- printf(" info\t\tshow details about last completed backup of device\n");
- printf(" list\t\tlist files of last completed backup in CSV format\n");
- printf(" unback\tunpack a completed backup in DIRECTORY/_unback_/\n");
- printf(" encryption on|off [PWD]\tenable or disable backup encryption\n");
- printf(" changepw [OLD NEW] change backup password on target device\n");
- printf(" cloud on|off\tenable or disable cloud use (requires iCloud account)\n");
- printf("\n");
- printf("NOTE: Passwords will be requested in interactive mode (-i) if omitted, or can\n");
- printf("be passed via environment variable BACKUP_PASSWORD/BACKUP_PASSWORD_NEW.\n");
- printf("See man page for further details.\n");
- printf("\n");
- printf("OPTIONS:\n");
- printf(" -u, --udid UDID\ttarget specific device by UDID\n");
- printf(" -s, --source UDID\tuse backup data from device specified by UDID\n");
- printf(" -n, --network\t\tconnect to network device\n");
- printf(" -i, --interactive\trequest passwords interactively\n");
- printf(" -d, --debug\t\tenable communication debugging\n");
- printf(" -h, --help\t\tprints usage information\n");
- printf(" -v, --version\t\tprints version information\n");
- printf("\n");
- printf("Homepage: <" PACKAGE_URL ">\n");
- printf("Bug Reports: <" PACKAGE_BUGREPORT ">\n");
+ char *name = strrchr(argv[0], '/');
+ fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] CMD [CMDOPTIONS] DIRECTORY\n", (name ? name + 1: argv[0]));
+ fprintf(is_error ? stderr : stdout,
+ "\n"
+ "Create or restore backup in/from the specified directory.\n"
+ "\n"
+ "CMD:\n"
+ " backup create backup for the device\n"
+ " --full force full backup from device.\n"
+ " restore restore last backup to the device\n"
+ " --system restore system files, too.\n"
+ " --no-reboot do NOT reboot the device when done (default: yes).\n"
+ " --copy create a copy of backup folder before restoring.\n"
+ " --settings restore device settings from the backup.\n"
+ " --remove remove items which are not being restored\n"
+ " --skip-apps do not trigger re-installation of apps after restore\n"
+ " --password PWD supply the password for the encrypted source backup\n"
+ " info show details about last completed backup of device\n"
+ " list list files of last completed backup in CSV format\n"
+ " unback unpack a completed backup in DIRECTORY/_unback_/\n"
+ " encryption on|off [PWD] enable or disable backup encryption\n"
+ " changepw [OLD NEW] change backup password on target device\n"
+ " cloud on|off enable or disable cloud use (requires iCloud account)\n"
+ "\n"
+ "NOTE: Passwords will be requested in interactive mode (-i) if omitted, or can\n"
+ "be passed via environment variable BACKUP_PASSWORD/BACKUP_PASSWORD_NEW.\n"
+ "See man page for further details.\n"
+ "\n"
+ "OPTIONS:\n"
+ " -u, --udid UDID target specific device by UDID\n"
+ " -s, --source UDID use backup data from device specified by UDID\n"
+ " -n, --network connect to network device\n"
+ " -i, --interactive request passwords interactively\n"
+ " -d, --debug enable communication debugging\n"
+ " -h, --help prints usage information\n"
+ " -v, --version prints version information\n"
+ "\n"
+ "Homepage: <" PACKAGE_URL ">\n"
+ "Bug Reports: <" PACKAGE_BUGREPORT ">\n"
+ );
}
#define DEVICE_VERSION(maj, min, patch) ((((maj) & 0xFF) << 16) | (((min) & 0xFF) << 8) | ((patch) & 0xFF))
@@ -1464,7 +1466,7 @@ int main(int argc, char *argv[])
{
idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR;
- int i;
+ int i = 0;
char* udid = NULL;
char* source_udid = NULL;
int use_network = 0;
@@ -1490,6 +1492,38 @@ int main(int argc, char *argv[])
mobilebackup2_error_t err;
uint64_t lockfile = 0;
+#define OPT_SYSTEM 1
+#define OPT_REBOOT 2
+#define OPT_NO_REBOOT 3
+#define OPT_COPY 4
+#define OPT_SETTINGS 5
+#define OPT_REMOVE 6
+#define OPT_SKIP_APPS 7
+#define OPT_PASSWORD 8
+#define OPT_FULL 9
+
+ int c = 0;
+ const struct option longopts[] = {
+ { "debug", no_argument, NULL, 'd' },
+ { "help", no_argument, NULL, 'h' },
+ { "udid", required_argument, NULL, 'u' },
+ { "source", required_argument, NULL, 's' },
+ { "interactive", no_argument, NULL, 'i' },
+ { "network", no_argument, NULL, 'n' },
+ { "version", no_argument, NULL, 'v' },
+ // command options:
+ { "system", no_argument, NULL, OPT_SYSTEM },
+ { "reboot", no_argument, NULL, OPT_REBOOT },
+ { "no-reboot", no_argument, NULL, OPT_NO_REBOOT },
+ { "copy", no_argument, NULL, OPT_COPY },
+ { "settings", no_argument, NULL, OPT_SETTINGS },
+ { "remove", no_argument, NULL, OPT_REMOVE },
+ { "skip-apps", no_argument, NULL, OPT_SKIP_APPS },
+ { "password", no_argument, NULL, OPT_PASSWORD },
+ { "full", no_argument, NULL, OPT_FULL },
+ { NULL, 0, NULL, 0}
+ };
+
/* we need to exit cleanly on running backups and restores or we cause havok */
signal(SIGINT, clean_exit);
signal(SIGTERM, clean_exit);
@@ -1499,201 +1533,192 @@ int main(int argc, char *argv[])
#endif
/* parse cmdline args */
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) {
+ while ((c = getopt_long(argc, argv, "dhu:s:inv", longopts, NULL)) != -1) {
+ switch (c) {
+ case 'd':
idevice_set_debug_level(1);
- continue;
- }
- else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) {
- i++;
- if (!argv[i] || !*argv[i]) {
- print_usage(argc, argv);
- return -1;
+ break;
+ case 'u':
+ if (!*optarg) {
+ fprintf(stderr, "ERROR: UDID argument must not be empty!\n");
+ print_usage(argc, argv, 1);
+ return 2;
}
- udid = strdup(argv[i]);
- continue;
- }
- else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--source")) {
- i++;
- if (!argv[i] || !*argv[i]) {
- print_usage(argc, argv);
- return -1;
+ udid = strdup(optarg);
+ break;
+ case 's':
+ if (!*optarg) {
+ fprintf(stderr, "ERROR: SOURCE argument must not be empty!\n");
+ print_usage(argc, argv, 1);
+ return 2;
}
- source_udid = strdup(argv[i]);
- continue;
- }
- else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--network")) {
- use_network = 1;
- continue;
- }
- else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--interactive")) {
+ source_udid = strdup(optarg);
+ case 'i':
interactive_mode = 1;
- continue;
- }
- else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
- print_usage(argc, argv);
+ break;
+ case 'n':
+ use_network = 1;
+ break;
+ case 'h':
+ print_usage(argc, argv, 0);
return 0;
- }
- else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
+ case 'v':
printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION);
return 0;
- }
- else if (!strcmp(argv[i], "backup")) {
- cmd = CMD_BACKUP;
- }
- else if (!strcmp(argv[i], "restore")) {
- cmd = CMD_RESTORE;
- }
- else if (!strcmp(argv[i], "--system")) {
+ case OPT_SYSTEM:
cmd_flags |= CMD_FLAG_RESTORE_SYSTEM_FILES;
- }
- else if (!strcmp(argv[i], "--reboot")) {
+ break;
+ case OPT_REBOOT:
cmd_flags &= ~CMD_FLAG_RESTORE_NO_REBOOT;
- }
- else if (!strcmp(argv[i], "--no-reboot")) {
+ break;
+ case OPT_NO_REBOOT:
cmd_flags |= CMD_FLAG_RESTORE_NO_REBOOT;
- }
- else if (!strcmp(argv[i], "--copy")) {
+ break;
+ case OPT_COPY:
cmd_flags |= CMD_FLAG_RESTORE_COPY_BACKUP;
- }
- else if (!strcmp(argv[i], "--settings")) {
+ break;
+ case OPT_SETTINGS:
cmd_flags |= CMD_FLAG_RESTORE_SETTINGS;
- }
- else if (!strcmp(argv[i], "--remove")) {
+ break;
+ case OPT_REMOVE:
cmd_flags |= CMD_FLAG_RESTORE_REMOVE_ITEMS;
- }
- else if (!strcmp(argv[i], "--skip-apps")) {
+ break;
+ case OPT_SKIP_APPS:
cmd_flags |= CMD_FLAG_RESTORE_SKIP_APPS;
- }
- else if (!strcmp(argv[i], "--password")) {
- i++;
- if (!argv[i]) {
- print_usage(argc, argv);
- return -1;
- }
- if (backup_password)
- free(backup_password);
- backup_password = strdup(argv[i]);
- continue;
- }
- else if (!strcmp(argv[i], "cloud")) {
- cmd = CMD_CLOUD;
- i++;
- if (!argv[i]) {
- printf("No argument given for cloud command; requires either 'on' or 'off'.\n");
- print_usage(argc, argv);
- return -1;
- }
- if (!strcmp(argv[i], "on")) {
- cmd_flags |= CMD_FLAG_CLOUD_ENABLE;
- } else if (!strcmp(argv[i], "off")) {
- cmd_flags |= CMD_FLAG_CLOUD_DISABLE;
- } else {
- printf("Invalid argument '%s' for cloud command; must be either 'on' or 'off'.\n", argv[i]);
- }
- continue;
- }
- else if (!strcmp(argv[i], "--full")) {
+ break;
+ case OPT_PASSWORD:
+ free(backup_password);
+ backup_password = strdup(optarg);
+ break;
+ case OPT_FULL:
cmd_flags |= CMD_FLAG_FORCE_FULL_BACKUP;
+ default:
+ print_usage(argc, argv, 1);
+ return 2;
}
- else if (!strcmp(argv[i], "info")) {
- cmd = CMD_INFO;
- verbose = 0;
- }
- else if (!strcmp(argv[i], "list")) {
- cmd = CMD_LIST;
- verbose = 0;
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (!argv[0]) {
+ fprintf(stderr, "ERROR: No command specified.\n");
+ print_usage(argc+optind, argv-optind, 1);
+ return 2;
+ }
+
+ if (!strcmp(argv[0], "backup")) {
+ cmd = CMD_BACKUP;
+ i = 1;
+ }
+ else if (!strcmp(argv[0], "restore")) {
+ cmd = CMD_RESTORE;
+ i = 1;
+ }
+ else if (!strcmp(argv[0], "cloud")) {
+ cmd = CMD_CLOUD;
+ i = 1;
+ if (!argv[i]) {
+ fprintf(stderr, "ERROR: No argument given for cloud command; requires either 'on' or 'off'.\n");
+ print_usage(argc+optind, argv-optind, 1);
+ return 2;
}
- else if (!strcmp(argv[i], "unback")) {
- cmd = CMD_UNBACK;
+ if (!strcmp(argv[i], "on")) {
+ cmd_flags |= CMD_FLAG_CLOUD_ENABLE;
+ } else if (!strcmp(argv[i], "off")) {
+ cmd_flags |= CMD_FLAG_CLOUD_DISABLE;
+ } else {
+ fprintf(stderr, "ERROR: Invalid argument '%s' for cloud command; must be either 'on' or 'off'.\n", argv[i]);
+ print_usage(argc+optind, argv-optind, 1);
+ return 2;
+ }
+ }
+ else if (!strcmp(argv[0], "info")) {
+ cmd = CMD_INFO;
+ verbose = 0;
+ }
+ else if (!strcmp(argv[0], "list")) {
+ cmd = CMD_LIST;
+ verbose = 0;
+ }
+ else if (!strcmp(argv[0], "unback")) {
+ cmd = CMD_UNBACK;
+ }
+ else if (!strcmp(argv[0], "encryption")) {
+ cmd = CMD_CHANGEPW;
+ i = 1;
+ if (!argv[i]) {
+ fprintf(stderr, "ERROR: No argument given for encryption command; requires either 'on' or 'off'.\n");
+ print_usage(argc+optind, argv-optind, 1);
+ return 2;
+ }
+ if (!strcmp(argv[i], "on")) {
+ cmd_flags |= CMD_FLAG_ENCRYPTION_ENABLE;
+ } else if (!strcmp(argv[i], "off")) {
+ cmd_flags |= CMD_FLAG_ENCRYPTION_DISABLE;
+ } else {
+ fprintf(stderr, "ERROR: Invalid argument '%s' for encryption command; must be either 'on' or 'off'.\n", argv[i]);
+ print_usage(argc+optind, argv-optind, 1);
+ return 2;
}
- else if (!strcmp(argv[i], "encryption")) {
- cmd = CMD_CHANGEPW;
- i++;
- if (!argv[i]) {
- printf("No argument given for encryption command; requires either 'on' or 'off'.\n");
- print_usage(argc, argv);
- return -1;
- }
- if (!strcmp(argv[i], "on")) {
- cmd_flags |= CMD_FLAG_ENCRYPTION_ENABLE;
- } else if (!strcmp(argv[i], "off")) {
- cmd_flags |= CMD_FLAG_ENCRYPTION_DISABLE;
- } else {
- printf("Invalid argument '%s' for encryption command; must be either 'on' or 'off'.\n", argv[i]);
- }
- // check if a password was given on the command line
- if (newpw) {
- free(newpw);
- newpw = NULL;
- }
- if (backup_password) {
- free(backup_password);
- backup_password = NULL;
- }
- i++;
- if (argv[i]) {
- if (cmd_flags & CMD_FLAG_ENCRYPTION_ENABLE) {
- newpw = strdup(argv[i]);
- } else if (cmd_flags & CMD_FLAG_ENCRYPTION_DISABLE) {
- backup_password = strdup(argv[i]);
- }
+ // check if a password was given on the command line
+ free(newpw);
+ newpw = NULL;
+ free(backup_password);
+ backup_password = NULL;
+ i++;
+ if (argv[i]) {
+ if (cmd_flags & CMD_FLAG_ENCRYPTION_ENABLE) {
+ newpw = strdup(argv[i]);
+ } else if (cmd_flags & CMD_FLAG_ENCRYPTION_DISABLE) {
+ backup_password = strdup(argv[i]);
}
- continue;
}
- else if (!strcmp(argv[i], "changepw")) {
- cmd = CMD_CHANGEPW;
- cmd_flags |= CMD_FLAG_ENCRYPTION_CHANGEPW;
- // check if passwords were given on command line
- if (newpw) {
- free(newpw);
- newpw = NULL;
- }
- if (backup_password) {
- free(backup_password);
- backup_password = NULL;
- }
+ }
+ else if (!strcmp(argv[0], "changepw")) {
+ cmd = CMD_CHANGEPW;
+ cmd_flags |= CMD_FLAG_ENCRYPTION_CHANGEPW;
+ // check if passwords were given on command line
+ free(newpw);
+ newpw = NULL;
+ free(backup_password);
+ backup_password = NULL;
+ i = 1;
+ if (argv[i]) {
+ backup_password = strdup(argv[i]);
i++;
- if (argv[i]) {
- backup_password = strdup(argv[i]);
- i++;
- if (!argv[i]) {
- printf("Old and new passwords have to be passed as arguments for the changepw command\n");
- print_usage(argc, argv);
- return -1;
- }
- newpw = strdup(argv[i]);
+ if (!argv[i]) {
+ fprintf(stderr, "ERROR: Old and new passwords have to be passed as arguments for the changepw command\n");
+ print_usage(argc+optind, argv-optind, 1);
+ return 2;
}
- continue;
- }
- else if (backup_directory == NULL) {
- backup_directory = argv[i];
- }
- else {
- print_usage(argc, argv);
- return -1;
+ newpw = strdup(argv[i]);
}
}
+ i++;
+ if (argv[i]) {
+ backup_directory = argv[i];
+ }
+
/* verify options */
if (cmd == -1) {
- printf("No command specified.\n");
- print_usage(argc, argv);
- return -1;
+ fprintf(stderr, "ERROR: Unsupported command '%s'.\n", argv[0]);
+ print_usage(argc+optind, argv-optind, 1);
+ return 2;
}
if (cmd == CMD_CHANGEPW || cmd == CMD_CLOUD) {
backup_directory = (char*)".this_folder_is_not_present_on_purpose";
} else {
if (backup_directory == NULL) {
- printf("No target backup directory specified.\n");
- print_usage(argc, argv);
- return -1;
+ fprintf(stderr, "ERROR: No target backup directory specified.\n");
+ print_usage(argc+optind, argv-optind, 1);
+ return 2;
}
/* verify if passed backup directory exists */
if (stat(backup_directory, &st) != 0) {
- printf("ERROR: Backup directory \"%s\" does not exist!\n", backup_directory);
+ fprintf(stderr, "ERROR: Backup directory \"%s\" does not exist!\n", backup_directory);
return -1;
}
}