summaryrefslogtreecommitdiffstats
path: root/tools/idevicedate.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/idevicedate.c')
-rw-r--r--tools/idevicedate.c265
1 files changed, 169 insertions, 96 deletions
diff --git a/tools/idevicedate.c b/tools/idevicedate.c
index e4e0a33..d05f63e 100644
--- a/tools/idevicedate.c
+++ b/tools/idevicedate.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * idevicedate.c 2 * idevicedate.c
3 * Simple utility to get and set the clock on an iDevice 3 * Simple utility to get and set the clock on a device
4 * 4 *
5 * Copyright (c) 2011 Martin Szulecki All Rights Reserved. 5 * Copyright (c) 2011 Martin Szulecki All Rights Reserved.
6 * 6 *
@@ -8,176 +8,249 @@
8 * modify it under the terms of the GNU Lesser General Public 8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version. 10 * version 2.1 of the License, or (at your option) any later version.
11 * 11 *
12 * This library is distributed in the hope that it will be useful, 12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details. 15 * Lesser General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU Lesser General Public 17 * 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 18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */ 20 */
21 21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
25
26#define TOOL_NAME "idevicedate"
27
22#include <stdio.h> 28#include <stdio.h>
23#include <stdlib.h> 29#include <stdlib.h>
24#include <string.h> 30#include <string.h>
31#include <getopt.h>
25#include <time.h> 32#include <time.h>
26#if HAVE_LANGINFO_CODESET 33#if HAVE_LANGINFO_CODESET
27# include <langinfo.h> 34#include <langinfo.h>
35#endif
36#ifndef WIN32
37#include <signal.h>
28#endif 38#endif
29 39
30#include <libimobiledevice/libimobiledevice.h> 40#include <libimobiledevice/libimobiledevice.h>
31#include <libimobiledevice/lockdown.h> 41#include <libimobiledevice/lockdown.h>
32 42
33#ifdef _DATE_FMT 43#ifdef _DATE_FMT
34# define DATE_FMT_LANGINFO() nl_langinfo (_DATE_FMT) 44#define DATE_FMT_LANGINFO nl_langinfo (_DATE_FMT)
45#else
46#ifdef WIN32
47#define DATE_FMT_LANGINFO "%a %b %#d %H:%M:%S %Z %Y"
35#else 48#else
36# define DATE_FMT_LANGINFO() "" 49#define DATE_FMT_LANGINFO "%a %b %e %H:%M:%S %Z %Y"
50#endif
37#endif 51#endif
38 52
39static void print_usage(int argc, char **argv) 53static void print_usage(int argc, char **argv, int is_error)
40{ 54{
41 char *name = NULL; 55 char *name = strrchr(argv[0], '/');
42 56 fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS]\n", (name ? name + 1: argv[0]));
43 name = strrchr(argv[0], '/'); 57 fprintf(is_error ? stderr : stdout,
44 printf("Usage: %s [OPTIONS]\n", (name ? name + 1: argv[0])); 58 "\n"
45 printf("Display the current date or set it on an iDevice.\n\n"); 59 "Display the current date or set it on a device.\n"
46 printf(" -d, --debug\t\tenable communication debugging\n"); 60 "\n"
47 printf(" -u, --uuid UUID\ttarget specific device by its 40-digit device UUID\n"); 61 "NOTE: Setting the time on iOS 6 and later is only supported\n"
48 printf(" -s, --set TIMESTAMP\tset UTC time described by TIMESTAMP\n"); 62 " in the setup wizard screens before device activation.\n"
49 printf(" -c, --sync\t\tset time of device to current system time\n"); 63 "\n"
50 printf(" -h, --help\t\tprints usage information\n"); 64 "OPTIONS:\n"
51 printf("\n"); 65 " -u, --udid UDID target specific device by UDID\n"
66 " -n, --network connect to network device\n"
67 " -s, --set TIMESTAMP set UTC time described by TIMESTAMP\n"
68 " -c, --sync set time of device to current system time\n"
69 " -d, --debug enable communication debugging\n"
70 " -h, --help prints usage information\n"
71 " -v, --version prints version information\n"
72 "\n"
73 "Homepage: <" PACKAGE_URL ">\n"
74 "Bug Reports: <" PACKAGE_BUGREPORT ">\n"
75 );
52} 76}
53 77
54int main(int argc, char *argv[]) 78int main(int argc, char *argv[])
55{ 79{
56 lockdownd_client_t client = NULL; 80 lockdownd_client_t client = NULL;
57 idevice_t phone = NULL; 81 lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR;
82 idevice_t device = NULL;
58 idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; 83 idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
59 int i; 84 const char* udid = NULL;
60 char uuid[41]; 85 int use_network = 0;
61 time_t setdate = 0; 86 time_t setdate = 0;
62 plist_t node = NULL; 87 plist_t node = NULL;
63 uuid[0] = 0; 88 int node_type = -1;
64 uint64_t datetime = 0; 89 uint64_t datetime = 0;
65 time_t rawtime; 90 time_t rawtime;
66 struct tm * tmp; 91 struct tm * tmp;
67 char const *format = NULL;
68 char buffer[80]; 92 char buffer[80];
93 int result = 0;
94
95 int c = 0;
96 const struct option longopts[] = {
97 { "debug", no_argument, NULL, 'd' },
98 { "help", no_argument, NULL, 'h' },
99 { "udid", required_argument, NULL, 'u' },
100 { "network", no_argument, NULL, 'n' },
101 { "version", no_argument, NULL, 'v' },
102 { "set", required_argument, NULL, 's' },
103 { "sync", no_argument, NULL, 'c' },
104 { NULL, 0, NULL, 0}
105 };
69 106
107#ifndef WIN32
108 signal(SIGPIPE, SIG_IGN);
109#endif
70 /* parse cmdline args */ 110 /* parse cmdline args */
71 for (i = 1; i < argc; i++) { 111 while ((c = getopt_long(argc, argv, "dhu:nvs:c", longopts, NULL)) != -1) {
72 if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { 112 switch (c) {
113 case 'd':
73 idevice_set_debug_level(1); 114 idevice_set_debug_level(1);
74 continue; 115 break;
75 } 116 case 'u':
76 else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--uuid")) { 117 if (!*optarg) {
77 i++; 118 fprintf(stderr, "ERROR: UDID argument must not be empty!\n");
78 if (!argv[i] || (strlen(argv[i]) != 40)) { 119 print_usage(argc, argv, 1);
79 print_usage(argc, argv); 120 return 2;
80 return 0;
81 } 121 }
82 strcpy(uuid, argv[i]); 122 udid = optarg;
83 continue; 123 break;
84 } 124 case 'n':
85 else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--set")) { 125 use_network = 1;
86 i++; 126 break;
87 if (!argv[i] || (strlen(argv[i]) <= 1)) { 127 case 'h':
88 print_usage(argc, argv); 128 print_usage(argc, argv, 0);
89 return 0; 129 return 0;
130 case 'v':
131 printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION);
132 return 0;
133 case 's':
134 if (!*optarg) {
135 fprintf(stderr, "ERROR: set argument must not be empty!\n");
136 print_usage(argc, argv, 1);
137 return 2;
90 } 138 }
91 setdate = atoi(argv[i]); 139 setdate = atoi(optarg);
92 if (setdate == 0) { 140 if (setdate == 0) {
93 printf("ERROR: Invalid timestamp value.\n"); 141 fprintf(stderr, "ERROR: Invalid timestamp value.\n");
94 print_usage(argc, argv); 142 print_usage(argc, argv, 1);
95 return 0; 143 return 0;
96 } 144 }
97 continue; 145 break;
98 } 146 case 'c':
99 else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--sync")) {
100 i++;
101 /* get current time */ 147 /* get current time */
102 setdate = time(NULL); 148 setdate = time(NULL);
103 /* convert it to local time which sets timezone/daylight variables */ 149 /* convert it to local time which sets timezone/daylight variables */
104 tmp = localtime(&setdate); 150 tmp = localtime(&setdate);
105 /* recalculate to make it UTC */ 151 /* recalculate to make it UTC */
106 setdate = mktime(tmp); 152 setdate = mktime(tmp);
107 continue; 153 break;
108 } 154 default:
109 else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { 155 print_usage(argc, argv, 1);
110 print_usage(argc, argv); 156 return 2;
111 return 0;
112 }
113 else {
114 print_usage(argc, argv);
115 return 0;
116 } 157 }
117 } 158 }
159 argc -= optind;
160 argv += optind;
118 161
119 /* determine a date format */ 162 ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX);
120 if (!format) { 163 if (ret != IDEVICE_E_SUCCESS) {
121 format = DATE_FMT_LANGINFO (); 164 if (udid) {
122 if (!*format) { 165 printf("No device found with udid %s.\n", udid);
123 format = "%a %b %e %H:%M:%S %Z %Y"; 166 } else {
167 printf("No device found.\n");
124 } 168 }
169 return -1;
125 } 170 }
126 171
127 if (uuid[0] != 0) { 172 if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(device, &client, TOOL_NAME))) {
128 ret = idevice_new(&phone, uuid); 173 fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", ldret);
129 if (ret != IDEVICE_E_SUCCESS) { 174 result = -1;
130 printf("No device found with uuid %s, is it plugged in?\n", uuid); 175 goto cleanup;
131 return -1;
132 }
133 } 176 }
134 else 177
135 { 178 if(lockdownd_get_value(client, NULL, "TimeIntervalSince1970", &node) != LOCKDOWN_E_SUCCESS) {
136 ret = idevice_new(&phone, NULL); 179 fprintf(stderr, "ERROR: Unable to retrieve 'TimeIntervalSince1970' node from device.\n");
137 if (ret != IDEVICE_E_SUCCESS) { 180 result = -1;
138 printf("No device found, is it plugged in?\n"); 181 goto cleanup;
139 return -1;
140 }
141 } 182 }
142 183
143 if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(phone, &client, "idevicedate")) { 184 if (node == NULL) {
144 idevice_free(phone); 185 fprintf(stderr, "ERROR: Empty node for 'TimeIntervalSince1970' received.\n");
145 return -1; 186 result = -1;
187 goto cleanup;
146 } 188 }
147 189
190 node_type = plist_get_node_type(node);
191
148 /* get or set? */ 192 /* get or set? */
149 if (setdate == 0) { 193 if (setdate == 0) {
150 /* get time value from device */ 194 /* get time value from device */
151 if(lockdownd_get_value(client, NULL, "TimeIntervalSince1970", &node) == LOCKDOWN_E_SUCCESS) { 195 switch (node_type) {
152 if (node) { 196 case PLIST_UINT:
153 plist_get_uint_val(node, &datetime); 197 plist_get_uint_val(node, &datetime);
154 plist_free(node); 198 break;
155 node = NULL; 199 case PLIST_REAL:
200 {
201 double rv = 0;
202 plist_get_real_val(node, &rv);
203 datetime = rv;
204 }
205 break;
206 default:
207 fprintf(stderr, "ERROR: Unexpected node type for 'TimeIntervalSince1970'\n");
208 break;
209 }
210 plist_free(node);
211 node = NULL;
156 212
157 /* date/time calculations */ 213 /* date/time calculations */
158 rawtime = (time_t)datetime; 214 rawtime = (time_t)datetime;
159 tmp = localtime(&rawtime); 215 tmp = localtime(&rawtime);
160 216
161 /* finally we format and print the current date */ 217 /* finally we format and print the current date */
162 strftime(buffer, 80, format, tmp); 218 strftime(buffer, 80, DATE_FMT_LANGINFO, tmp);
163 puts(buffer); 219 puts(buffer);
164 }
165 }
166 } else { 220 } else {
167 datetime = setdate; 221 datetime = setdate;
168 222
169 if(lockdownd_set_value(client, NULL, "TimeIntervalSince1970", plist_new_uint(datetime)) == LOCKDOWN_E_SUCCESS) { 223 plist_free(node);
224 node = NULL;
225
226 switch (node_type) {
227 case PLIST_UINT:
228 node = plist_new_uint(datetime);
229 break;
230 case PLIST_REAL:
231 node = plist_new_real((double)datetime);
232 break;
233 default:
234 fprintf(stderr, "ERROR: Unexpected node type for 'TimeIntervalSince1970'\n");
235 break;
236 }
237
238 if(lockdownd_set_value(client, NULL, "TimeIntervalSince1970", node) == LOCKDOWN_E_SUCCESS) {
170 tmp = localtime(&setdate); 239 tmp = localtime(&setdate);
171 strftime(buffer, 80, format, tmp); 240 strftime(buffer, 80, DATE_FMT_LANGINFO, tmp);
172 puts(buffer); 241 puts(buffer);
173 } else { 242 } else {
174 printf("ERROR: Failed to set date on device.\n"); 243 printf("ERROR: Failed to set date on device.\n");
175 } 244 }
245 node = NULL;
176 } 246 }
177 247
178 lockdownd_client_free(client); 248cleanup:
179 idevice_free(phone); 249 if (client)
250 lockdownd_client_free(client);
180 251
181 return 0; 252 if (device)
182} 253 idevice_free(device);
183 254
255 return result;
256}