summaryrefslogtreecommitdiffstats
path: root/src/mobile_image_mounter.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2010-02-17 16:25:51 +0100
committerGravatar Matt Colyer2010-02-19 09:34:33 -0800
commitf364f1984e3d3ea2baa18ec7e939f912ddc06dbf (patch)
tree65dc7c6b90c135db0fe78ae3baac5dd74970433e /src/mobile_image_mounter.c
parentaaa1f20562068872cbba7e1f53d051a40a8ac4a4 (diff)
downloadlibimobiledevice-f364f1984e3d3ea2baa18ec7e939f912ddc06dbf.tar.gz
libimobiledevice-f364f1984e3d3ea2baa18ec7e939f912ddc06dbf.tar.bz2
New mobile_image_mounter interface plus ideviceimagemounter tool
Diffstat (limited to 'src/mobile_image_mounter.c')
-rw-r--r--src/mobile_image_mounter.c271
1 files changed, 271 insertions, 0 deletions
diff --git a/src/mobile_image_mounter.c b/src/mobile_image_mounter.c
new file mode 100644
index 0000000..7fe0a6d
--- /dev/null
+++ b/src/mobile_image_mounter.c
@@ -0,0 +1,271 @@
1/*
2 * mobile_image_mounter.c
3 * MobileImageMounter implementation.
4 *
5 * Copyright (c) 2010 Nikias Bassen, 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.
11 *
12 * 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.
16 *
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
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <string.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <unistd.h>
26#include <arpa/inet.h>
27#include <plist/plist.h>
28
29#include "mobile_image_mounter.h"
30#include "property_list_service.h"
31#include "debug.h"
32
33/** Locks an MobileImageMounter client, done for thread safety stuff.
34 *
35 * @param client The MIM to lock
36 */
37static void mobile_image_mounter_lock(mobile_image_mounter_client_t client)
38{
39 g_mutex_lock(client->mutex);
40}
41
42/** Unlocks an MIM client, done for thread safety stuff.
43 *
44 * @param client The MIM to unlock
45 */
46static void mobile_image_mounter_unlock(mobile_image_mounter_client_t client)
47{
48 g_mutex_unlock(client->mutex);
49}
50
51/**
52 * Convert a property_list_service_error_t value to a
53 * mobile_image_mounter_error_t value.
54 * Used internally to get correct error codes.
55 *
56 * @param err A property_list_service_error_t error code
57 *
58 * @return A matching mobile_image_mounter_error_t error code,
59 * MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR otherwise.
60 */
61static mobile_image_mounter_error_t mobile_image_mounter_error(property_list_service_error_t err)
62{
63 switch (err) {
64 case PROPERTY_LIST_SERVICE_E_SUCCESS:
65 return MOBILE_IMAGE_MOUNTER_E_SUCCESS;
66 case PROPERTY_LIST_SERVICE_E_INVALID_ARG:
67 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
68 case PROPERTY_LIST_SERVICE_E_PLIST_ERROR:
69 return MOBILE_IMAGE_MOUNTER_E_PLIST_ERROR;
70 case PROPERTY_LIST_SERVICE_E_MUX_ERROR:
71 return MOBILE_IMAGE_MOUNTER_E_CONN_FAILED;
72 default:
73 break;
74 }
75 return MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR;
76}
77
78/**
79 * Makes a connection to the MobileImageMounter service on the phone.
80 *
81 * @param device The device to connect to.
82 * @param port Destination port (usually given by lockdownd_start_service).
83 * @param client Pointer that will be set to a newly allocated
84 * mobile_image_mounter_client_t upon successful return.
85 *
86 * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success,
87 * MOBILE_IMAGE_MOUNTER_E_INVALID_ARG when device is NULL,
88 * or MOBILE_IMAGE_MOUNTER_E_CONN_FAILED when the connection to the
89 * device could not be established.
90 */
91mobile_image_mounter_error_t mobile_image_mounter_new(idevice_t device, uint16_t port, mobile_image_mounter_client_t *client)
92{
93 /* makes sure thread environment is available */
94 if (!g_thread_supported())
95 g_thread_init(NULL);
96
97 if (!device)
98 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
99
100 property_list_service_client_t plistclient = NULL;
101 if (property_list_service_client_new(device, port, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) {
102 return MOBILE_IMAGE_MOUNTER_E_CONN_FAILED;
103 }
104
105 mobile_image_mounter_client_t client_loc = (mobile_image_mounter_client_t) malloc(sizeof(struct mobile_image_mounter_client_int));
106 client_loc->parent = plistclient;
107
108 client_loc->mutex = g_mutex_new();
109
110 *client = client_loc;
111 return MOBILE_IMAGE_MOUNTER_E_SUCCESS;
112}
113
114/**
115 * Disconnects an MobileImageMounter client from the device.
116 *
117 * @param client The client to disconnect.
118 *
119 * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success,
120 * or MOBILE_IMAGE_MOUNTER_E_INVALID_ARG when client is NULL.
121 */
122mobile_image_mounter_error_t mobile_image_mounter_free(mobile_image_mounter_client_t client)
123{
124 if (!client)
125 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
126
127 property_list_service_client_free(client->parent);
128 client->parent = NULL;
129 if (client->mutex) {
130 g_mutex_free(client->mutex);
131 }
132 free(client);
133
134 return MOBILE_IMAGE_MOUNTER_E_SUCCESS;
135}
136
137/**
138 * Tells if the image of ImageType is already mounted.
139 *
140 * @param client The client use
141 * @param image_type The type of the image to look up
142 * @param result Pointer to a plist that will receive the result of the
143 * operation.
144 *
145 * @note This function may return MOBILE_IMAGE_MOUNTER_E_SUCCESS even if the
146 * operation has failed. Check the resulting plist for further information.
147 *
148 * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success, or an error code on error
149 */
150mobile_image_mounter_error_t mobile_image_mounter_lookup_image(mobile_image_mounter_client_t client, const char *image_type, plist_t *result)
151{
152 if (!client || !image_type || !result) {
153 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
154 }
155 mobile_image_mounter_lock(client);
156
157 plist_t dict = plist_new_dict();
158 plist_dict_insert_item(dict,"Command", plist_new_string("LookupImage"));
159 plist_dict_insert_item(dict,"ImageType", plist_new_string(image_type));
160
161 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
162 plist_free(dict);
163
164 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
165 debug_info("%s: Error sending XML plist to device!", __func__);
166 goto leave_unlock;
167 }
168
169 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, result));
170 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
171 debug_info("%s: Error receiving response from device!", __func__);
172 }
173
174leave_unlock:
175 mobile_image_mounter_unlock(client);
176 return res;
177}
178
179/**
180 * Mounts an image on the device.
181 *
182 * @param client The connected MobileImageMounter client.
183 * @param image_path The absolute path of the image to mount. The image must
184 * be present before calling this function.
185 * @param image_signature Pointer to a buffer holding the images' signature
186 * @param signature_length Length of the signature image_signature points to
187 * @param image_type Type of image to mount
188 * @param result Pointer to a plist that will receive the result of the
189 * operation.
190 *
191 * @note This function may return MOBILE_IMAGE_MOUNTER_E_SUCCESS even if the
192 * operation has failed. Check the resulting plist for further information.
193 *
194 * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success,
195 * MOBILE_IMAGE_MOUNTER_E_INVALID_ARG when on ore more parameters are
196 * invalid, or another error code otherwise.
197 */
198mobile_image_mounter_error_t mobile_image_mounter_mount_image(mobile_image_mounter_client_t client, const char *image_path, const char *image_signature, uint16_t signature_length, const char *image_type, plist_t *result)
199{
200 if (!client || !image_path || !image_signature || (signature_length == 0) || !image_type || !result) {
201 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
202 }
203 mobile_image_mounter_lock(client);
204
205 plist_t dict = plist_new_dict();
206 plist_dict_insert_item(dict, "Command", plist_new_string("MountImage"));
207 plist_dict_insert_item(dict, "ImagePath", plist_new_string(image_path));
208 plist_dict_insert_item(dict, "ImageSignature", plist_new_data(image_signature, signature_length));
209 plist_dict_insert_item(dict, "ImageType", plist_new_string(image_type));
210
211 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
212 plist_free(dict);
213
214 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
215 debug_info("%s: Error sending XML plist to device!", __func__);
216 goto leave_unlock;
217 }
218
219 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, result));
220 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
221 debug_info("%s: Error receiving response from device!", __func__);
222 }
223
224leave_unlock:
225 mobile_image_mounter_unlock(client);
226 return res;
227}
228
229/**
230 * Hangs up the connection to the MobileImageMounter service.
231 * This functions has to be called before freeing up a mobile_image_mounter
232 * instance. If not, errors appear in the device's syslog.
233 *
234 * @param client The client to hang up
235 *
236 * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success,
237 * MOBILE_IMAGE_MOUNTER_E_INVALID_ARG if client is invalid,
238 * or another error code otherwise.
239 */
240mobile_image_mounter_error_t mobile_image_mounter_hangup(mobile_image_mounter_client_t client)
241{
242 if (!client) {
243 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
244 }
245 mobile_image_mounter_lock(client);
246
247 plist_t dict = plist_new_dict();
248 plist_dict_insert_item(dict, "Command", plist_new_string("Hangup"));
249
250 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
251 plist_free(dict);
252
253 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
254 debug_info("%s: Error sending XML plist to device!", __func__);
255 goto leave_unlock;
256 }
257
258 dict = NULL;
259 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &dict));
260 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
261 debug_info("%s: Error receiving response from device!", __func__);
262 }
263 if (dict) {
264 debug_plist(dict);
265 plist_free(dict);
266 }
267
268leave_unlock:
269 mobile_image_mounter_unlock(client);
270 return res;
271}