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 @@
36#include <libgen.h> 36#include <libgen.h>
37#include <ctype.h> 37#include <ctype.h>
38#include <time.h> 38#include <time.h>
39#include <getopt.h>
39 40
40#include <libimobiledevice/libimobiledevice.h> 41#include <libimobiledevice/libimobiledevice.h>
41#include <libimobiledevice/lockdown.h> 42#include <libimobiledevice/lockdown.h>
@@ -1415,47 +1416,48 @@ static void clean_exit(int sig)
1415 quit_flag++; 1416 quit_flag++;
1416} 1417}
1417 1418
1418static void print_usage(int argc, char **argv) 1419static void print_usage(int argc, char **argv, int is_error)
1419{ 1420{
1420 char *name = NULL; 1421 char *name = strrchr(argv[0], '/');
1421 name = strrchr(argv[0], '/'); 1422 fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] CMD [CMDOPTIONS] DIRECTORY\n", (name ? name + 1: argv[0]));
1422 printf("Usage: %s [OPTIONS] CMD [CMDOPTIONS] DIRECTORY\n", (name ? name + 1: argv[0])); 1423 fprintf(is_error ? stderr : stdout,
1423 printf("\n"); 1424 "\n"
1424 printf("Create or restore backup from the current or specified directory.\n"); 1425 "Create or restore backup in/from the specified directory.\n"
1425 printf("\n"); 1426 "\n"
1426 printf("CMD:\n"); 1427 "CMD:\n"
1427 printf(" backup\tcreate backup for the device\n"); 1428 " backup create backup for the device\n"
1428 printf(" --full\t\tforce full backup from device.\n"); 1429 " --full force full backup from device.\n"
1429 printf(" restore\trestore last backup to the device\n"); 1430 " restore restore last backup to the device\n"
1430 printf(" --system\t\trestore system files, too.\n"); 1431 " --system restore system files, too.\n"
1431 printf(" --no-reboot\t\tdo NOT reboot the device when done (default: yes).\n"); 1432 " --no-reboot do NOT reboot the device when done (default: yes).\n"
1432 printf(" --copy\t\tcreate a copy of backup folder before restoring.\n"); 1433 " --copy create a copy of backup folder before restoring.\n"
1433 printf(" --settings\t\trestore device settings from the backup.\n"); 1434 " --settings restore device settings from the backup.\n"
1434 printf(" --remove\t\tremove items which are not being restored\n"); 1435 " --remove remove items which are not being restored\n"
1435 printf(" --skip-apps\t\tdo not trigger re-installation of apps after restore\n"); 1436 " --skip-apps do not trigger re-installation of apps after restore\n"
1436 printf(" --password PWD\tsupply the password for the encrypted source backup\n"); 1437 " --password PWD supply the password for the encrypted source backup\n"
1437 printf(" info\t\tshow details about last completed backup of device\n"); 1438 " info show details about last completed backup of device\n"
1438 printf(" list\t\tlist files of last completed backup in CSV format\n"); 1439 " list list files of last completed backup in CSV format\n"
1439 printf(" unback\tunpack a completed backup in DIRECTORY/_unback_/\n"); 1440 " unback unpack a completed backup in DIRECTORY/_unback_/\n"
1440 printf(" encryption on|off [PWD]\tenable or disable backup encryption\n"); 1441 " encryption on|off [PWD] enable or disable backup encryption\n"
1441 printf(" changepw [OLD NEW] change backup password on target device\n"); 1442 " changepw [OLD NEW] change backup password on target device\n"
1442 printf(" cloud on|off\tenable or disable cloud use (requires iCloud account)\n"); 1443 " cloud on|off enable or disable cloud use (requires iCloud account)\n"
1443 printf("\n"); 1444 "\n"
1444 printf("NOTE: Passwords will be requested in interactive mode (-i) if omitted, or can\n"); 1445 "NOTE: Passwords will be requested in interactive mode (-i) if omitted, or can\n"
1445 printf("be passed via environment variable BACKUP_PASSWORD/BACKUP_PASSWORD_NEW.\n"); 1446 "be passed via environment variable BACKUP_PASSWORD/BACKUP_PASSWORD_NEW.\n"
1446 printf("See man page for further details.\n"); 1447 "See man page for further details.\n"
1447 printf("\n"); 1448 "\n"
1448 printf("OPTIONS:\n"); 1449 "OPTIONS:\n"
1449 printf(" -u, --udid UDID\ttarget specific device by UDID\n"); 1450 " -u, --udid UDID target specific device by UDID\n"
1450 printf(" -s, --source UDID\tuse backup data from device specified by UDID\n"); 1451 " -s, --source UDID use backup data from device specified by UDID\n"
1451 printf(" -n, --network\t\tconnect to network device\n"); 1452 " -n, --network connect to network device\n"
1452 printf(" -i, --interactive\trequest passwords interactively\n"); 1453 " -i, --interactive request passwords interactively\n"
1453 printf(" -d, --debug\t\tenable communication debugging\n"); 1454 " -d, --debug enable communication debugging\n"
1454 printf(" -h, --help\t\tprints usage information\n"); 1455 " -h, --help prints usage information\n"
1455 printf(" -v, --version\t\tprints version information\n"); 1456 " -v, --version prints version information\n"
1456 printf("\n"); 1457 "\n"
1457 printf("Homepage: <" PACKAGE_URL ">\n"); 1458 "Homepage: <" PACKAGE_URL ">\n"
1458 printf("Bug Reports: <" PACKAGE_BUGREPORT ">\n"); 1459 "Bug Reports: <" PACKAGE_BUGREPORT ">\n"
1460 );
1459} 1461}
1460 1462
1461#define DEVICE_VERSION(maj, min, patch) ((((maj) & 0xFF) << 16) | (((min) & 0xFF) << 8) | ((patch) & 0xFF)) 1463#define DEVICE_VERSION(maj, min, patch) ((((maj) & 0xFF) << 16) | (((min) & 0xFF) << 8) | ((patch) & 0xFF))
@@ -1464,7 +1466,7 @@ int main(int argc, char *argv[])
1464{ 1466{
1465 idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; 1467 idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
1466 lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR; 1468 lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR;
1467 int i; 1469 int i = 0;
1468 char* udid = NULL; 1470 char* udid = NULL;
1469 char* source_udid = NULL; 1471 char* source_udid = NULL;
1470 int use_network = 0; 1472 int use_network = 0;
@@ -1490,6 +1492,38 @@ int main(int argc, char *argv[])
1490 mobilebackup2_error_t err; 1492 mobilebackup2_error_t err;
1491 uint64_t lockfile = 0; 1493 uint64_t lockfile = 0;
1492 1494
1495#define OPT_SYSTEM 1
1496#define OPT_REBOOT 2
1497#define OPT_NO_REBOOT 3
1498#define OPT_COPY 4
1499#define OPT_SETTINGS 5
1500#define OPT_REMOVE 6
1501#define OPT_SKIP_APPS 7
1502#define OPT_PASSWORD 8
1503#define OPT_FULL 9
1504
1505 int c = 0;
1506 const struct option longopts[] = {
1507 { "debug", no_argument, NULL, 'd' },
1508 { "help", no_argument, NULL, 'h' },
1509 { "udid", required_argument, NULL, 'u' },
1510 { "source", required_argument, NULL, 's' },
1511 { "interactive", no_argument, NULL, 'i' },
1512 { "network", no_argument, NULL, 'n' },
1513 { "version", no_argument, NULL, 'v' },
1514 // command options:
1515 { "system", no_argument, NULL, OPT_SYSTEM },
1516 { "reboot", no_argument, NULL, OPT_REBOOT },
1517 { "no-reboot", no_argument, NULL, OPT_NO_REBOOT },
1518 { "copy", no_argument, NULL, OPT_COPY },
1519 { "settings", no_argument, NULL, OPT_SETTINGS },
1520 { "remove", no_argument, NULL, OPT_REMOVE },
1521 { "skip-apps", no_argument, NULL, OPT_SKIP_APPS },
1522 { "password", no_argument, NULL, OPT_PASSWORD },
1523 { "full", no_argument, NULL, OPT_FULL },
1524 { NULL, 0, NULL, 0}
1525 };
1526
1493 /* we need to exit cleanly on running backups and restores or we cause havok */ 1527 /* we need to exit cleanly on running backups and restores or we cause havok */
1494 signal(SIGINT, clean_exit); 1528 signal(SIGINT, clean_exit);
1495 signal(SIGTERM, clean_exit); 1529 signal(SIGTERM, clean_exit);
@@ -1499,201 +1533,192 @@ int main(int argc, char *argv[])
1499#endif 1533#endif
1500 1534
1501 /* parse cmdline args */ 1535 /* parse cmdline args */
1502 for (i = 1; i < argc; i++) { 1536 while ((c = getopt_long(argc, argv, "dhu:s:inv", longopts, NULL)) != -1) {
1503 if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { 1537 switch (c) {
1538 case 'd':
1504 idevice_set_debug_level(1); 1539 idevice_set_debug_level(1);
1505 continue; 1540 break;
1506 } 1541 case 'u':
1507 else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { 1542 if (!*optarg) {
1508 i++; 1543 fprintf(stderr, "ERROR: UDID argument must not be empty!\n");
1509 if (!argv[i] || !*argv[i]) { 1544 print_usage(argc, argv, 1);
1510 print_usage(argc, argv); 1545 return 2;
1511 return -1;
1512 } 1546 }
1513 udid = strdup(argv[i]); 1547 udid = strdup(optarg);
1514 continue; 1548 break;
1515 } 1549 case 's':
1516 else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--source")) { 1550 if (!*optarg) {
1517 i++; 1551 fprintf(stderr, "ERROR: SOURCE argument must not be empty!\n");
1518 if (!argv[i] || !*argv[i]) { 1552 print_usage(argc, argv, 1);
1519 print_usage(argc, argv); 1553 return 2;
1520 return -1;
1521 } 1554 }
1522 source_udid = strdup(argv[i]); 1555 source_udid = strdup(optarg);
1523 continue; 1556 case 'i':
1524 }
1525 else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--network")) {
1526 use_network = 1;
1527 continue;
1528 }
1529 else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--interactive")) {
1530 interactive_mode = 1; 1557 interactive_mode = 1;
1531 continue; 1558 break;
1532 } 1559 case 'n':
1533 else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { 1560 use_network = 1;
1534 print_usage(argc, argv); 1561 break;
1562 case 'h':
1563 print_usage(argc, argv, 0);
1535 return 0; 1564 return 0;
1536 } 1565 case 'v':
1537 else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
1538 printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION); 1566 printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION);
1539 return 0; 1567 return 0;
1540 } 1568 case OPT_SYSTEM:
1541 else if (!strcmp(argv[i], "backup")) {
1542 cmd = CMD_BACKUP;
1543 }
1544 else if (!strcmp(argv[i], "restore")) {
1545 cmd = CMD_RESTORE;
1546 }
1547 else if (!strcmp(argv[i], "--system")) {
1548 cmd_flags |= CMD_FLAG_RESTORE_SYSTEM_FILES; 1569 cmd_flags |= CMD_FLAG_RESTORE_SYSTEM_FILES;
1549 } 1570 break;
1550 else if (!strcmp(argv[i], "--reboot")) { 1571 case OPT_REBOOT:
1551 cmd_flags &= ~CMD_FLAG_RESTORE_NO_REBOOT; 1572 cmd_flags &= ~CMD_FLAG_RESTORE_NO_REBOOT;
1552 } 1573 break;
1553 else if (!strcmp(argv[i], "--no-reboot")) { 1574 case OPT_NO_REBOOT:
1554 cmd_flags |= CMD_FLAG_RESTORE_NO_REBOOT; 1575 cmd_flags |= CMD_FLAG_RESTORE_NO_REBOOT;
1555 } 1576 break;
1556 else if (!strcmp(argv[i], "--copy")) { 1577 case OPT_COPY:
1557 cmd_flags |= CMD_FLAG_RESTORE_COPY_BACKUP; 1578 cmd_flags |= CMD_FLAG_RESTORE_COPY_BACKUP;
1558 } 1579 break;
1559 else if (!strcmp(argv[i], "--settings")) { 1580 case OPT_SETTINGS:
1560 cmd_flags |= CMD_FLAG_RESTORE_SETTINGS; 1581 cmd_flags |= CMD_FLAG_RESTORE_SETTINGS;
1561 } 1582 break;
1562 else if (!strcmp(argv[i], "--remove")) { 1583 case OPT_REMOVE:
1563 cmd_flags |= CMD_FLAG_RESTORE_REMOVE_ITEMS; 1584 cmd_flags |= CMD_FLAG_RESTORE_REMOVE_ITEMS;
1564 } 1585 break;
1565 else if (!strcmp(argv[i], "--skip-apps")) { 1586 case OPT_SKIP_APPS:
1566 cmd_flags |= CMD_FLAG_RESTORE_SKIP_APPS; 1587 cmd_flags |= CMD_FLAG_RESTORE_SKIP_APPS;
1567 } 1588 break;
1568 else if (!strcmp(argv[i], "--password")) { 1589 case OPT_PASSWORD:
1569 i++; 1590 free(backup_password);
1570 if (!argv[i]) { 1591 backup_password = strdup(optarg);
1571 print_usage(argc, argv); 1592 break;
1572 return -1; 1593 case OPT_FULL:
1573 }
1574 if (backup_password)
1575 free(backup_password);
1576 backup_password = strdup(argv[i]);
1577 continue;
1578 }
1579 else if (!strcmp(argv[i], "cloud")) {
1580 cmd = CMD_CLOUD;
1581 i++;
1582 if (!argv[i]) {
1583 printf("No argument given for cloud command; requires either 'on' or 'off'.\n");
1584 print_usage(argc, argv);
1585 return -1;
1586 }
1587 if (!strcmp(argv[i], "on")) {
1588 cmd_flags |= CMD_FLAG_CLOUD_ENABLE;
1589 } else if (!strcmp(argv[i], "off")) {
1590 cmd_flags |= CMD_FLAG_CLOUD_DISABLE;
1591 } else {
1592 printf("Invalid argument '%s' for cloud command; must be either 'on' or 'off'.\n", argv[i]);
1593 }
1594 continue;
1595 }
1596 else if (!strcmp(argv[i], "--full")) {
1597 cmd_flags |= CMD_FLAG_FORCE_FULL_BACKUP; 1594 cmd_flags |= CMD_FLAG_FORCE_FULL_BACKUP;
1595 default:
1596 print_usage(argc, argv, 1);
1597 return 2;
1598 } 1598 }
1599 else if (!strcmp(argv[i], "info")) { 1599 }
1600 cmd = CMD_INFO; 1600 argc -= optind;
1601 verbose = 0; 1601 argv += optind;
1602 } 1602
1603 else if (!strcmp(argv[i], "list")) { 1603 if (!argv[0]) {
1604 cmd = CMD_LIST; 1604 fprintf(stderr, "ERROR: No command specified.\n");
1605 verbose = 0; 1605 print_usage(argc+optind, argv-optind, 1);
1606 return 2;
1607 }
1608
1609 if (!strcmp(argv[0], "backup")) {
1610 cmd = CMD_BACKUP;
1611 i = 1;
1612 }
1613 else if (!strcmp(argv[0], "restore")) {
1614 cmd = CMD_RESTORE;
1615 i = 1;
1616 }
1617 else if (!strcmp(argv[0], "cloud")) {
1618 cmd = CMD_CLOUD;
1619 i = 1;
1620 if (!argv[i]) {
1621 fprintf(stderr, "ERROR: No argument given for cloud command; requires either 'on' or 'off'.\n");
1622 print_usage(argc+optind, argv-optind, 1);
1623 return 2;
1606 } 1624 }
1607 else if (!strcmp(argv[i], "unback")) { 1625 if (!strcmp(argv[i], "on")) {
1608 cmd = CMD_UNBACK; 1626 cmd_flags |= CMD_FLAG_CLOUD_ENABLE;
1627 } else if (!strcmp(argv[i], "off")) {
1628 cmd_flags |= CMD_FLAG_CLOUD_DISABLE;
1629 } else {
1630 fprintf(stderr, "ERROR: Invalid argument '%s' for cloud command; must be either 'on' or 'off'.\n", argv[i]);
1631 print_usage(argc+optind, argv-optind, 1);
1632 return 2;
1633 }
1634 }
1635 else if (!strcmp(argv[0], "info")) {
1636 cmd = CMD_INFO;
1637 verbose = 0;
1638 }
1639 else if (!strcmp(argv[0], "list")) {
1640 cmd = CMD_LIST;
1641 verbose = 0;
1642 }
1643 else if (!strcmp(argv[0], "unback")) {
1644 cmd = CMD_UNBACK;
1645 }
1646 else if (!strcmp(argv[0], "encryption")) {
1647 cmd = CMD_CHANGEPW;
1648 i = 1;
1649 if (!argv[i]) {
1650 fprintf(stderr, "ERROR: No argument given for encryption command; requires either 'on' or 'off'.\n");
1651 print_usage(argc+optind, argv-optind, 1);
1652 return 2;
1653 }
1654 if (!strcmp(argv[i], "on")) {
1655 cmd_flags |= CMD_FLAG_ENCRYPTION_ENABLE;
1656 } else if (!strcmp(argv[i], "off")) {
1657 cmd_flags |= CMD_FLAG_ENCRYPTION_DISABLE;
1658 } else {
1659 fprintf(stderr, "ERROR: Invalid argument '%s' for encryption command; must be either 'on' or 'off'.\n", argv[i]);
1660 print_usage(argc+optind, argv-optind, 1);
1661 return 2;
1609 } 1662 }
1610 else if (!strcmp(argv[i], "encryption")) { 1663 // check if a password was given on the command line
1611 cmd = CMD_CHANGEPW; 1664 free(newpw);
1612 i++; 1665 newpw = NULL;
1613 if (!argv[i]) { 1666 free(backup_password);
1614 printf("No argument given for encryption command; requires either 'on' or 'off'.\n"); 1667 backup_password = NULL;
1615 print_usage(argc, argv); 1668 i++;
1616 return -1; 1669 if (argv[i]) {
1617 } 1670 if (cmd_flags & CMD_FLAG_ENCRYPTION_ENABLE) {
1618 if (!strcmp(argv[i], "on")) { 1671 newpw = strdup(argv[i]);
1619 cmd_flags |= CMD_FLAG_ENCRYPTION_ENABLE; 1672 } else if (cmd_flags & CMD_FLAG_ENCRYPTION_DISABLE) {
1620 } else if (!strcmp(argv[i], "off")) { 1673 backup_password = strdup(argv[i]);
1621 cmd_flags |= CMD_FLAG_ENCRYPTION_DISABLE;
1622 } else {
1623 printf("Invalid argument '%s' for encryption command; must be either 'on' or 'off'.\n", argv[i]);
1624 }
1625 // check if a password was given on the command line
1626 if (newpw) {
1627 free(newpw);
1628 newpw = NULL;
1629 }
1630 if (backup_password) {
1631 free(backup_password);
1632 backup_password = NULL;
1633 }
1634 i++;
1635 if (argv[i]) {
1636 if (cmd_flags & CMD_FLAG_ENCRYPTION_ENABLE) {
1637 newpw = strdup(argv[i]);
1638 } else if (cmd_flags & CMD_FLAG_ENCRYPTION_DISABLE) {
1639 backup_password = strdup(argv[i]);
1640 }
1641 } 1674 }
1642 continue;
1643 } 1675 }
1644 else if (!strcmp(argv[i], "changepw")) { 1676 }
1645 cmd = CMD_CHANGEPW; 1677 else if (!strcmp(argv[0], "changepw")) {
1646 cmd_flags |= CMD_FLAG_ENCRYPTION_CHANGEPW; 1678 cmd = CMD_CHANGEPW;
1647 // check if passwords were given on command line 1679 cmd_flags |= CMD_FLAG_ENCRYPTION_CHANGEPW;
1648 if (newpw) { 1680 // check if passwords were given on command line
1649 free(newpw); 1681 free(newpw);
1650 newpw = NULL; 1682 newpw = NULL;
1651 } 1683 free(backup_password);
1652 if (backup_password) { 1684 backup_password = NULL;
1653 free(backup_password); 1685 i = 1;
1654 backup_password = NULL; 1686 if (argv[i]) {
1655 } 1687 backup_password = strdup(argv[i]);
1656 i++; 1688 i++;
1657 if (argv[i]) { 1689 if (!argv[i]) {
1658 backup_password = strdup(argv[i]); 1690 fprintf(stderr, "ERROR: Old and new passwords have to be passed as arguments for the changepw command\n");
1659 i++; 1691 print_usage(argc+optind, argv-optind, 1);
1660 if (!argv[i]) { 1692 return 2;
1661 printf("Old and new passwords have to be passed as arguments for the changepw command\n");
1662 print_usage(argc, argv);
1663 return -1;
1664 }
1665 newpw = strdup(argv[i]);
1666 } 1693 }
1667 continue; 1694 newpw = strdup(argv[i]);
1668 }
1669 else if (backup_directory == NULL) {
1670 backup_directory = argv[i];
1671 }
1672 else {
1673 print_usage(argc, argv);
1674 return -1;
1675 } 1695 }
1676 } 1696 }
1677 1697
1698 i++;
1699 if (argv[i]) {
1700 backup_directory = argv[i];
1701 }
1702
1678 /* verify options */ 1703 /* verify options */
1679 if (cmd == -1) { 1704 if (cmd == -1) {
1680 printf("No command specified.\n"); 1705 fprintf(stderr, "ERROR: Unsupported command '%s'.\n", argv[0]);
1681 print_usage(argc, argv); 1706 print_usage(argc+optind, argv-optind, 1);
1682 return -1; 1707 return 2;
1683 } 1708 }
1684 1709
1685 if (cmd == CMD_CHANGEPW || cmd == CMD_CLOUD) { 1710 if (cmd == CMD_CHANGEPW || cmd == CMD_CLOUD) {
1686 backup_directory = (char*)".this_folder_is_not_present_on_purpose"; 1711 backup_directory = (char*)".this_folder_is_not_present_on_purpose";
1687 } else { 1712 } else {
1688 if (backup_directory == NULL) { 1713 if (backup_directory == NULL) {
1689 printf("No target backup directory specified.\n"); 1714 fprintf(stderr, "ERROR: No target backup directory specified.\n");
1690 print_usage(argc, argv); 1715 print_usage(argc+optind, argv-optind, 1);
1691 return -1; 1716 return 2;
1692 } 1717 }
1693 1718
1694 /* verify if passed backup directory exists */ 1719 /* verify if passed backup directory exists */
1695 if (stat(backup_directory, &st) != 0) { 1720 if (stat(backup_directory, &st) != 0) {
1696 printf("ERROR: Backup directory \"%s\" does not exist!\n", backup_directory); 1721 fprintf(stderr, "ERROR: Backup directory \"%s\" does not exist!\n", backup_directory);
1697 return -1; 1722 return -1;
1698 } 1723 }
1699 } 1724 }