blob: 29cc5c9ca17009a8f1592cfa49668c2e17de2fb6 [file] [log] [blame]
Martin Szulecki5844d662009-08-01 18:54:59 +02001/*
Nikias Bassen96101a12010-01-28 22:18:41 +01002 * ideviceenterrecovery.c
Martin Szulecki5844d662009-08-01 18:54:59 +02003 * Simple utility to make a device in normal mode enter recovery mode.
4 *
5 * Copyright (c) 2009 Martin Szulecki All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
Martin Szulecki24ce2e22015-01-28 01:27:59 +010011 *
Martin Szulecki5844d662009-08-01 18:54:59 +020012 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
Martin Szulecki24ce2e22015-01-28 01:27:59 +010016 *
Martin Szulecki5844d662009-08-01 18:54:59 +020017 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
Martin Szulecki24ce2e22015-01-28 01:27:59 +010019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Martin Szulecki5844d662009-08-01 18:54:59 +020020 */
21
Martin Szuleckid93043e2015-10-06 22:10:56 +020022#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
25
Nikias Bassen3aa4e242020-06-05 18:42:20 +020026#define TOOL_NAME "ideviceenterrecovery"
27
Martin Szulecki5844d662009-08-01 18:54:59 +020028#include <stdio.h>
29#include <string.h>
Martin Szulecki5844d662009-08-01 18:54:59 +020030#include <stdlib.h>
Nikias Bassen6cb13f92022-04-30 13:31:20 +020031#include <getopt.h>
32#include <errno.h>
Nikias Bassen8c7321b2019-09-28 12:08:12 +020033#ifndef WIN32
34#include <signal.h>
35#endif
Martin Szulecki5844d662009-08-01 18:54:59 +020036
Nikias Bassen96101a12010-01-28 22:18:41 +010037#include <libimobiledevice/libimobiledevice.h>
38#include <libimobiledevice/lockdown.h>
Martin Szulecki5844d662009-08-01 18:54:59 +020039
Nikias Bassen6cb13f92022-04-30 13:31:20 +020040static void print_usage(int argc, char **argv, int is_error)
Martin Szulecki5844d662009-08-01 18:54:59 +020041{
Nikias Bassen6cb13f92022-04-30 13:31:20 +020042 char *name = strrchr(argv[0], '/');
43 fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] UDID\n", (name ? name + 1: argv[0]));
44 fprintf(is_error ? stderr : stdout,
45 "\n"
46 "Makes a device with the supplied UDID enter recovery mode immediately.\n"
47 "\n"
48 "OPTIONS:\n"
49 " -d, --debug enable communication debugging\n"
50 " -h, --help prints usage information\n"
51 " -v, --version prints version information\n"
52 "\n"
53 "Homepage: <" PACKAGE_URL ">\n"
54 "Bug Reports: <" PACKAGE_BUGREPORT ">\n"
55 );
Martin Szulecki5844d662009-08-01 18:54:59 +020056}
57
58int main(int argc, char *argv[])
59{
60 lockdownd_client_t client = NULL;
Nikias Bassenfd435442014-10-11 22:12:04 +020061 lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR;
Nikias Bassen14bacd92012-11-29 04:02:18 +010062 idevice_t device = NULL;
Nikias Bassen96101a12010-01-28 22:18:41 +010063 idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
Nikias Bassen36c01922012-11-29 03:42:06 +010064 const char* udid = NULL;
Nikias Bassen6cb13f92022-04-30 13:31:20 +020065 int c = 0;
66 const struct option longopts[] = {
67 { "debug", no_argument, NULL, 'd' },
68 { "help", no_argument, NULL, 'h' },
69 { "version", no_argument, NULL, 'v' },
70 { NULL, 0, NULL, 0}
71 };
Martin Szulecki5844d662009-08-01 18:54:59 +020072
Nikias Bassen8c7321b2019-09-28 12:08:12 +020073#ifndef WIN32
74 signal(SIGPIPE, SIG_IGN);
75#endif
Martin Szulecki5844d662009-08-01 18:54:59 +020076 /* parse cmdline args */
Nikias Bassen6cb13f92022-04-30 13:31:20 +020077 while ((c = getopt_long(argc, argv, "dhv", longopts, NULL)) != -1) {
78 switch (c) {
79 case 'd':
Nikias Bassen96101a12010-01-28 22:18:41 +010080 idevice_set_debug_level(1);
Nikias Bassen6cb13f92022-04-30 13:31:20 +020081 break;
82 case 'h':
83 print_usage(argc, argv, 0);
Martin Szulecki5844d662009-08-01 18:54:59 +020084 return 0;
Nikias Bassen6cb13f92022-04-30 13:31:20 +020085 case 'v':
Nikias Bassen3aa4e242020-06-05 18:42:20 +020086 printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION);
87 return 0;
Nikias Bassen6cb13f92022-04-30 13:31:20 +020088 default:
89 print_usage(argc, argv, 1);
90 return 2;
Nikias Bassen3aa4e242020-06-05 18:42:20 +020091 }
Martin Szulecki5844d662009-08-01 18:54:59 +020092 }
Nikias Bassen6cb13f92022-04-30 13:31:20 +020093 argc -= optind;
94 argv += optind;
Martin Szulecki5844d662009-08-01 18:54:59 +020095
Nikias Bassen6cb13f92022-04-30 13:31:20 +020096 if (!argv[0]) {
97 fprintf(stderr, "ERROR: No UDID specified\n");
98 print_usage(argc+optind, argv-optind, 1);
99 return 2;
Martin Szulecki5844d662009-08-01 18:54:59 +0200100 }
Nikias Bassen6cb13f92022-04-30 13:31:20 +0200101 udid = argv[0];
Martin Szulecki5844d662009-08-01 18:54:59 +0200102
Nikias Bassen14bacd92012-11-29 04:02:18 +0100103 ret = idevice_new(&device, udid);
Nikias Bassen96101a12010-01-28 22:18:41 +0100104 if (ret != IDEVICE_E_SUCCESS) {
Nikias Bassen489a6732020-06-05 20:50:34 +0200105 printf("No device found with udid %s.\n", udid);
Nikias Bassen25059d42021-02-09 02:45:06 +0100106 return 1;
Martin Szulecki5844d662009-08-01 18:54:59 +0200107 }
108
Nikias Bassen3aa4e242020-06-05 18:42:20 +0200109 if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new(device, &client, TOOL_NAME))) {
Nikias Bassen25059d42021-02-09 02:45:06 +0100110 printf("ERROR: Could not connect to lockdownd: %s (%d)\n", lockdownd_strerror(ldret), ldret);
Nikias Bassen14bacd92012-11-29 04:02:18 +0100111 idevice_free(device);
Nikias Bassen25059d42021-02-09 02:45:06 +0100112 return 1;
Martin Szulecki5844d662009-08-01 18:54:59 +0200113 }
114
Nikias Bassen25059d42021-02-09 02:45:06 +0100115 int res = 0;
Martin Szulecki74573462012-03-22 16:07:07 +0100116 printf("Telling device with udid %s to enter recovery mode.\n", udid);
Nikias Bassen25059d42021-02-09 02:45:06 +0100117 ldret = lockdownd_enter_recovery(client);
118 if (ldret == LOCKDOWN_E_SESSION_INACTIVE) {
119 lockdownd_client_free(client);
120 client = NULL;
121 if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(device, &client, TOOL_NAME))) {
122 printf("ERROR: Could not connect to lockdownd: %s (%d)\n", lockdownd_strerror(ldret), ldret);
123 idevice_free(device);
124 return 1;
125 }
126 ldret = lockdownd_enter_recovery(client);
Martin Szulecki5844d662009-08-01 18:54:59 +0200127 }
Nikias Bassen25059d42021-02-09 02:45:06 +0100128 if (ldret != LOCKDOWN_E_SUCCESS) {
129 printf("Failed to enter recovery mode.\n");
130 res = 1;
131 } else {
132 printf("Device is successfully switching to recovery mode.\n");
133 }
Martin Szulecki5844d662009-08-01 18:54:59 +0200134
135 lockdownd_client_free(client);
Nikias Bassen14bacd92012-11-29 04:02:18 +0100136 idevice_free(device);
Martin Szulecki5844d662009-08-01 18:54:59 +0200137
Nikias Bassen25059d42021-02-09 02:45:06 +0100138 return res;
Martin Szulecki5844d662009-08-01 18:54:59 +0200139}