diff options
| author | 2009-07-26 19:34:22 -0700 | |
|---|---|---|
| committer | 2009-07-26 19:34:22 -0700 | |
| commit | eea538c94f01f8054f69f059614f19400187a472 (patch) | |
| tree | 209a12dc8c8eaece15b8153d15e689c8c2147ab6 /src/AFC.c | |
| parent | 8ebfd7d8eea89bb27e4e6dbb1f37fd90d98b439c (diff) | |
| parent | 19c9750d670435ce430f0fc85a55faf127bdfbf9 (diff) | |
| download | libimobiledevice-eea538c94f01f8054f69f059614f19400187a472.tar.gz libimobiledevice-eea538c94f01f8054f69f059614f19400187a472.tar.bz2 | |
Merge commit 'martin-s/martin'
[#46 state:resolved]
Diffstat (limited to 'src/AFC.c')
| -rw-r--r-- | src/AFC.c | 703 |
1 files changed, 326 insertions, 377 deletions
| @@ -21,15 +21,12 @@ | |||
| 21 | 21 | ||
| 22 | #include <stdio.h> | 22 | #include <stdio.h> |
| 23 | #include <stdlib.h> | 23 | #include <stdlib.h> |
| 24 | #include <errno.h> | ||
| 25 | #include <unistd.h> | 24 | #include <unistd.h> |
| 25 | |||
| 26 | #include "AFC.h" | 26 | #include "AFC.h" |
| 27 | #include "iphone.h" | 27 | #include "iphone.h" |
| 28 | #include "utils.h" | 28 | #include "utils.h" |
| 29 | 29 | ||
| 30 | #include <libiphone/afc.h> | ||
| 31 | |||
| 32 | |||
| 33 | // This is the maximum size an AFC data packet can be | 30 | // This is the maximum size an AFC data packet can be |
| 34 | const int MAXIMUM_PACKET_SIZE = (2 << 15); | 31 | const int MAXIMUM_PACKET_SIZE = (2 << 15); |
| 35 | 32 | ||
| @@ -39,11 +36,7 @@ const int MAXIMUM_PACKET_SIZE = (2 << 15); | |||
| 39 | */ | 36 | */ |
| 40 | static void afc_lock(afc_client_t client) | 37 | static void afc_lock(afc_client_t client) |
| 41 | { | 38 | { |
| 42 | log_debug_msg("Locked\n"); | 39 | log_debug_msg("%s: Locked\n", __func__); |
| 43 | /*while (client->lock) { | ||
| 44 | usleep(500); // they say it's obsolete, but whatever | ||
| 45 | } | ||
| 46 | client->lock = 1; */ | ||
| 47 | g_mutex_lock(client->mutex); | 40 | g_mutex_lock(client->mutex); |
| 48 | } | 41 | } |
| 49 | 42 | ||
| @@ -52,9 +45,8 @@ static void afc_lock(afc_client_t client) | |||
| 52 | * @param client The AFC | 45 | * @param client The AFC |
| 53 | */ | 46 | */ |
| 54 | static void afc_unlock(afc_client_t client) | 47 | static void afc_unlock(afc_client_t client) |
| 55 | { // just to be pretty | 48 | { |
| 56 | log_debug_msg("Unlocked\n"); | 49 | log_debug_msg("%s: Unlocked\n", __func__); |
| 57 | //client->lock = 0; | ||
| 58 | g_mutex_unlock(client->mutex); | 50 | g_mutex_unlock(client->mutex); |
| 59 | } | 51 | } |
| 60 | 52 | ||
| @@ -66,30 +58,30 @@ static void afc_unlock(afc_client_t client) | |||
| 66 | * | 58 | * |
| 67 | * @return A handle to the newly-connected client or NULL upon error. | 59 | * @return A handle to the newly-connected client or NULL upon error. |
| 68 | */ | 60 | */ |
| 69 | iphone_error_t afc_new_client(iphone_device_t device, int dst_port, afc_client_t * client) | 61 | afc_error_t afc_client_new(iphone_device_t device, int dst_port, afc_client_t * client) |
| 70 | { | 62 | { |
| 71 | //makes sure thread environment is available | 63 | /* makes sure thread environment is available */ |
| 72 | if (!g_thread_supported()) | 64 | if (!g_thread_supported()) |
| 73 | g_thread_init(NULL); | 65 | g_thread_init(NULL); |
| 74 | 66 | ||
| 75 | if (!device) | 67 | if (!device) |
| 76 | return IPHONE_E_INVALID_ARG; | 68 | return AFC_E_INVALID_ARGUMENT; |
| 77 | 69 | ||
| 78 | // Attempt connection | 70 | /* attempt connection */ |
| 79 | int sfd = usbmuxd_connect(device->handle, dst_port); | 71 | int sfd = usbmuxd_connect(device->handle, dst_port); |
| 80 | if (sfd < 0) { | 72 | if (sfd < 0) { |
| 81 | return IPHONE_E_UNKNOWN_ERROR; // ret; | 73 | return AFC_E_MUX_ERROR; |
| 82 | } | 74 | } |
| 83 | 75 | ||
| 84 | afc_client_t client_loc = (afc_client_t) malloc(sizeof(struct afc_client_int)); | 76 | afc_client_t client_loc = (afc_client_t) malloc(sizeof(struct afc_client_int)); |
| 85 | client_loc->sfd = sfd; | 77 | client_loc->sfd = sfd; |
| 86 | 78 | ||
| 87 | // Allocate a packet | 79 | /* allocate a packet */ |
| 88 | client_loc->afc_packet = (AFCPacket *) malloc(sizeof(AFCPacket)); | 80 | client_loc->afc_packet = (AFCPacket *) malloc(sizeof(AFCPacket)); |
| 89 | if (!client_loc->afc_packet) { | 81 | if (!client_loc->afc_packet) { |
| 90 | usbmuxd_disconnect(client_loc->sfd); | 82 | usbmuxd_disconnect(client_loc->sfd); |
| 91 | free(client_loc); | 83 | free(client_loc); |
| 92 | return IPHONE_E_UNKNOWN_ERROR; | 84 | return AFC_E_NO_MEM; |
| 93 | } | 85 | } |
| 94 | 86 | ||
| 95 | client_loc->afc_packet->packet_num = 0; | 87 | client_loc->afc_packet->packet_num = 0; |
| @@ -101,17 +93,17 @@ iphone_error_t afc_new_client(iphone_device_t device, int dst_port, afc_client_t | |||
| 101 | client_loc->mutex = g_mutex_new(); | 93 | client_loc->mutex = g_mutex_new(); |
| 102 | 94 | ||
| 103 | *client = client_loc; | 95 | *client = client_loc; |
| 104 | return IPHONE_E_SUCCESS; | 96 | return AFC_E_SUCCESS; |
| 105 | } | 97 | } |
| 106 | 98 | ||
| 107 | /** Disconnects an AFC client from the phone. | 99 | /** Disconnects an AFC client from the phone. |
| 108 | * | 100 | * |
| 109 | * @param client The client to disconnect. | 101 | * @param client The client to disconnect. |
| 110 | */ | 102 | */ |
| 111 | iphone_error_t afc_free_client(afc_client_t client) | 103 | afc_error_t afc_client_free(afc_client_t client) |
| 112 | { | 104 | { |
| 113 | if (!client || client->sfd < 0 || !client->afc_packet) | 105 | if (!client || client->sfd < 0 || !client->afc_packet) |
| 114 | return IPHONE_E_INVALID_ARG; | 106 | return AFC_E_INVALID_ARGUMENT; |
| 115 | 107 | ||
| 116 | usbmuxd_disconnect(client->sfd); | 108 | usbmuxd_disconnect(client->sfd); |
| 117 | free(client->afc_packet); | 109 | free(client->afc_packet); |
| @@ -119,88 +111,7 @@ iphone_error_t afc_free_client(afc_client_t client) | |||
| 119 | g_mutex_free(client->mutex); | 111 | g_mutex_free(client->mutex); |
| 120 | } | 112 | } |
| 121 | free(client); | 113 | free(client); |
| 122 | return IPHONE_E_SUCCESS; | 114 | return AFC_E_SUCCESS; |
| 123 | } | ||
| 124 | |||
| 125 | /** | ||
| 126 | * Returns the AFC error code that has been sent by the device if | ||
| 127 | * an error occured (set inside receive_AFC_data) | ||
| 128 | * | ||
| 129 | * @param client AFC client for that the error value is to be retrieved. | ||
| 130 | * | ||
| 131 | * @return AFC error code or -1 on error. | ||
| 132 | */ | ||
| 133 | int afc_get_afcerror(afc_client_t client) | ||
| 134 | { | ||
| 135 | int res = -1; | ||
| 136 | if (client) { | ||
| 137 | afc_lock(client); | ||
| 138 | res = client->afcerror; | ||
| 139 | afc_unlock(client); | ||
| 140 | } | ||
| 141 | return res; | ||
| 142 | } | ||
| 143 | |||
| 144 | /** | ||
| 145 | * Tries to convert the AFC error value into a meaningful errno value. | ||
| 146 | * Internally used by afc_get_errno. | ||
| 147 | * | ||
| 148 | * @param afcerror AFC error value to convert | ||
| 149 | * | ||
| 150 | * @return errno value or -1 if the errno could not be determined. | ||
| 151 | * | ||
| 152 | * @see afc_get_errno | ||
| 153 | */ | ||
| 154 | static int afcerror_to_errno(int afcerror) | ||
| 155 | { | ||
| 156 | int res = -1; | ||
| 157 | switch (afcerror) { | ||
| 158 | case 0: // ERROR_SUCCESS, this means no error. | ||
| 159 | res = 0; | ||
| 160 | break; | ||
| 161 | case 4: // occurs if you try to open a file as directory | ||
| 162 | res = ENOTDIR; | ||
| 163 | break; | ||
| 164 | case 7: // occurs e.g. if you try to close a file handle that | ||
| 165 | // does not belong to an open file | ||
| 166 | res = EINVAL; | ||
| 167 | break; | ||
| 168 | case 8: // occurs if you try to open a non-existent file | ||
| 169 | res = ENOENT; | ||
| 170 | break; | ||
| 171 | case 9: // occurs if you try to open a directory as file | ||
| 172 | res = EISDIR; | ||
| 173 | break; | ||
| 174 | case 10: // occurs if you try to open a file without permission | ||
| 175 | res = EPERM; | ||
| 176 | break; | ||
| 177 | default: // we'll assume it's an errno value, but report it | ||
| 178 | log_debug_msg("WARNING: unknown AFC error %d, perhaps it's '%s'?\n", afcerror, strerror(afcerror)); | ||
| 179 | res = afcerror; | ||
| 180 | break; | ||
| 181 | } | ||
| 182 | |||
| 183 | log_debug_msg("Mapped AFC error %d to errno %d: %s\n", afcerror, res, strerror(res)); | ||
| 184 | |||
| 185 | return res; | ||
| 186 | } | ||
| 187 | |||
| 188 | /** | ||
| 189 | * Returns the client's AFC error code converted to an errno value. | ||
| 190 | * | ||
| 191 | * @param client AFC client for that the errno value is to be retrieved. | ||
| 192 | * | ||
| 193 | * @return errno value or -1 on error. | ||
| 194 | */ | ||
| 195 | int afc_get_errno(afc_client_t client) | ||
| 196 | { | ||
| 197 | int res = -1; | ||
| 198 | if (client) { | ||
| 199 | afc_lock(client); | ||
| 200 | res = afcerror_to_errno(client->afcerror); | ||
| 201 | afc_unlock(client); | ||
| 202 | } | ||
| 203 | return res; | ||
| 204 | } | 115 | } |
| 205 | 116 | ||
| 206 | /** Dispatches an AFC packet over a client. | 117 | /** Dispatches an AFC packet over a client. |
| @@ -216,13 +127,14 @@ int afc_get_errno(afc_client_t client) | |||
| 216 | * reason is that if you set them to different values, it indicates | 127 | * reason is that if you set them to different values, it indicates |
| 217 | * you want to send the data as two packets. | 128 | * you want to send the data as two packets. |
| 218 | */ | 129 | */ |
| 219 | static int dispatch_AFC_packet(afc_client_t client, const char *data, uint64_t length) | 130 | static int afc_dispatch_packet(afc_client_t client, const char *data, uint64_t length) |
| 220 | { | 131 | { |
| 221 | int bytes = 0, offset = 0; | 132 | int bytes = 0, offset = 0; |
| 222 | char *buffer; | 133 | char *buffer; |
| 223 | 134 | ||
| 224 | if (!client || client->sfd < 0 || !client->afc_packet) | 135 | if (!client || client->sfd < 0 || !client->afc_packet) |
| 225 | return 0; | 136 | return 0; |
| 137 | |||
| 226 | if (!data || !length) | 138 | if (!data || !length) |
| 227 | length = 0; | 139 | length = 0; |
| 228 | 140 | ||
| @@ -242,12 +154,12 @@ static int dispatch_AFC_packet(afc_client_t client, const char *data, uint64_t l | |||
| 242 | memcpy(buffer, (char *) client->afc_packet, sizeof(AFCPacket)); | 154 | memcpy(buffer, (char *) client->afc_packet, sizeof(AFCPacket)); |
| 243 | offset = client->afc_packet->this_length - sizeof(AFCPacket); | 155 | offset = client->afc_packet->this_length - sizeof(AFCPacket); |
| 244 | 156 | ||
| 245 | log_debug_msg("dispatch_AFC_packet: Offset: %i\n", offset); | 157 | log_debug_msg("%s: Offset: %i\n", __func__, offset); |
| 246 | if ((length) < (client->afc_packet->entire_length - client->afc_packet->this_length)) { | 158 | if ((length) < (client->afc_packet->entire_length - client->afc_packet->this_length)) { |
| 247 | log_debug_msg("dispatch_AFC_packet: Length did not resemble what it was supposed"); | 159 | log_debug_msg("%s: Length did not resemble what it was supposed", __func__); |
| 248 | log_debug_msg("to based on the packet.\n"); | 160 | log_debug_msg("to based on the packet.\n"); |
| 249 | log_debug_msg("length minus offset: %i\n", length - offset); | 161 | log_debug_msg("%s: length minus offset: %i\n", __func__, length - offset); |
| 250 | log_debug_msg("rest of packet: %i\n", client->afc_packet->entire_length - client->afc_packet->this_length); | 162 | log_debug_msg("%s: rest of packet: %i\n", __func__, client->afc_packet->entire_length - client->afc_packet->this_length); |
| 251 | free(buffer); | 163 | free(buffer); |
| 252 | return -1; | 164 | return -1; |
| 253 | } | 165 | } |
| @@ -258,19 +170,19 @@ static int dispatch_AFC_packet(afc_client_t client, const char *data, uint64_t l | |||
| 258 | return bytes; | 170 | return bytes; |
| 259 | } | 171 | } |
| 260 | 172 | ||
| 261 | log_debug_msg("dispatch_AFC_packet: sent the first now go with the second\n"); | 173 | log_debug_msg("%s: sent the first now go with the second\n", __func__); |
| 262 | log_debug_msg("Length: %i\n", length - offset); | 174 | log_debug_msg("%s: Length: %i\n", __func__, length - offset); |
| 263 | log_debug_msg("Buffer: \n"); | 175 | log_debug_msg("%s: Buffer: \n", __func__); |
| 264 | log_debug_buffer(data + offset, length - offset); | 176 | log_debug_buffer(data + offset, length - offset); |
| 265 | 177 | ||
| 266 | usbmuxd_send(client->sfd, data + offset, length - offset, (uint32_t*)&bytes); | 178 | usbmuxd_send(client->sfd, data + offset, length - offset, (uint32_t*)&bytes); |
| 267 | return bytes; | 179 | return bytes; |
| 268 | } else { | 180 | } else { |
| 269 | log_debug_msg("dispatch_AFC_packet doin things the old way\n"); | 181 | log_debug_msg("%s: doin things the old way\n", __func__); |
| 270 | buffer = (char *) malloc(sizeof(char) * client->afc_packet->this_length); | 182 | buffer = (char *) malloc(sizeof(char) * client->afc_packet->this_length); |
| 271 | log_debug_msg("dispatch_AFC_packet packet length = %i\n", client->afc_packet->this_length); | 183 | log_debug_msg("%s: packet length = %i\n", __func__, client->afc_packet->this_length); |
| 272 | memcpy(buffer, (char *) client->afc_packet, sizeof(AFCPacket)); | 184 | memcpy(buffer, (char *) client->afc_packet, sizeof(AFCPacket)); |
| 273 | log_debug_msg("dispatch_AFC_packet packet data follows\n"); | 185 | log_debug_msg("%s: packet data follows\n", __func__); |
| 274 | if (length > 0) { | 186 | if (length > 0) { |
| 275 | memcpy(buffer + sizeof(AFCPacket), data, length); | 187 | memcpy(buffer + sizeof(AFCPacket), data, length); |
| 276 | } | 188 | } |
| @@ -297,83 +209,81 @@ static int dispatch_AFC_packet(afc_client_t client, const char *data, uint64_t l | |||
| 297 | * received raised a non-trivial error condition (i.e. non-zero with | 209 | * received raised a non-trivial error condition (i.e. non-zero with |
| 298 | * AFC_ERROR operation) | 210 | * AFC_ERROR operation) |
| 299 | */ | 211 | */ |
| 300 | static int receive_AFC_data(afc_client_t client, char **dump_here) | 212 | static afc_error_t afc_receive_data(afc_client_t client, char **dump_here, int *bytes) |
| 301 | { | 213 | { |
| 302 | AFCPacket header; | 214 | AFCPacket header; |
| 303 | int bytes = 0; | ||
| 304 | uint32_t entire_len = 0; | 215 | uint32_t entire_len = 0; |
| 305 | uint32_t this_len = 0; | 216 | uint32_t this_len = 0; |
| 306 | uint32_t current_count = 0; | 217 | uint32_t current_count = 0; |
| 307 | uint64_t param1 = -1; | 218 | uint64_t param1 = -1; |
| 308 | 219 | ||
| 309 | // reset internal afc error value | 220 | *bytes = 0; |
| 310 | client->afcerror = 0; | ||
| 311 | 221 | ||
| 312 | // first, read the AFC header | 222 | /* first, read the AFC header */ |
| 313 | usbmuxd_recv(client->sfd, (char*)&header, sizeof(AFCPacket), (uint32_t*)&bytes); | 223 | usbmuxd_recv(client->sfd, (char*)&header, sizeof(AFCPacket), (uint32_t*)bytes); |
| 314 | if (bytes <= 0) { | 224 | if (*bytes <= 0) { |
| 315 | log_debug_msg("%s: Just didn't get enough.\n", __func__); | 225 | log_debug_msg("%s: Just didn't get enough.\n", __func__); |
| 316 | *dump_here = NULL; | 226 | *dump_here = NULL; |
| 317 | return -1; | 227 | return AFC_E_MUX_ERROR; |
| 318 | } else if ((uint32_t)bytes < sizeof(AFCPacket)) { | 228 | } else if ((uint32_t)*bytes < sizeof(AFCPacket)) { |
| 319 | log_debug_msg("%s: Did not even get the AFCPacket header\n", __func__); | 229 | log_debug_msg("%s: Did not even get the AFCPacket header\n", __func__); |
| 320 | *dump_here = NULL; | 230 | *dump_here = NULL; |
| 321 | return -1; | 231 | return AFC_E_MUX_ERROR; |
| 322 | } | 232 | } |
| 323 | 233 | ||
| 324 | // check if it's a valid AFC header | 234 | /* check if it's a valid AFC header */ |
| 325 | if (strncmp(header.magic, AFC_MAGIC, AFC_MAGIC_LEN)) { | 235 | if (strncmp(header.magic, AFC_MAGIC, AFC_MAGIC_LEN)) { |
| 326 | log_debug_msg("%s: Invalid AFC packet received (magic != " AFC_MAGIC ")!\n", __func__); | 236 | log_debug_msg("%s: Invalid AFC packet received (magic != " AFC_MAGIC ")!\n", __func__); |
| 327 | } | 237 | } |
| 328 | 238 | ||
| 329 | // check if it has the correct packet number | 239 | /* check if it has the correct packet number */ |
| 330 | if (header.packet_num != client->afc_packet->packet_num) { | 240 | if (header.packet_num != client->afc_packet->packet_num) { |
| 331 | // otherwise print a warning but do not abort | 241 | /* otherwise print a warning but do not abort */ |
| 332 | log_debug_msg("%s: ERROR: Unexpected packet number (%lld != %lld) aborting.\n", __func__, header.packet_num, client->afc_packet->packet_num); | 242 | log_debug_msg("%s: ERROR: Unexpected packet number (%lld != %lld) aborting.\n", __func__, header.packet_num, client->afc_packet->packet_num); |
| 333 | *dump_here = NULL; | 243 | *dump_here = NULL; |
| 334 | return -1; | 244 | return AFC_E_OP_HEADER_INVALID; |
| 335 | } | 245 | } |
| 336 | 246 | ||
| 337 | // then, read the attached packet | 247 | /* then, read the attached packet */ |
| 338 | if (header.this_length < sizeof(AFCPacket)) { | 248 | if (header.this_length < sizeof(AFCPacket)) { |
| 339 | log_debug_msg("%s: Invalid AFCPacket header received!\n", __func__); | 249 | log_debug_msg("%s: Invalid AFCPacket header received!\n", __func__); |
| 340 | *dump_here = NULL; | 250 | *dump_here = NULL; |
| 341 | return -1; | 251 | return AFC_E_OP_HEADER_INVALID; |
| 342 | } else if ((header.this_length == header.entire_length) | 252 | } else if ((header.this_length == header.entire_length) |
| 343 | && header.entire_length == sizeof(AFCPacket)) { | 253 | && header.entire_length == sizeof(AFCPacket)) { |
| 344 | log_debug_msg("%s: Empty AFCPacket received!\n", __func__); | 254 | log_debug_msg("%s: Empty AFCPacket received!\n", __func__); |
| 345 | *dump_here = NULL; | 255 | *dump_here = NULL; |
| 346 | if (header.operation == AFC_SUCCESS_RESPONSE) { | 256 | *bytes = 0; |
| 347 | return 0; | 257 | if (header.operation == AFC_OP_DATA) { |
| 258 | return AFC_E_SUCCESS; | ||
| 348 | } else { | 259 | } else { |
| 349 | client->afcerror = EIO; | 260 | return AFC_E_IO_ERROR; |
| 350 | return -1; | ||
| 351 | } | 261 | } |
| 352 | } | 262 | } |
| 353 | 263 | ||
| 354 | log_debug_msg("%s: received AFC packet, full len=%lld, this len=%lld, operation=%lld\n", __func__, header.entire_length, header.this_length, header.operation); | 264 | log_debug_msg("%s: received AFC packet, full len=%lld, this len=%lld, operation=0x%llx\n", __func__, header.entire_length, header.this_length, header.operation); |
| 355 | 265 | ||
| 356 | entire_len = (uint32_t)header.entire_length - sizeof(AFCPacket); | 266 | entire_len = (uint32_t)header.entire_length - sizeof(AFCPacket); |
| 357 | this_len = (uint32_t)header.this_length - sizeof(AFCPacket); | 267 | this_len = (uint32_t)header.this_length - sizeof(AFCPacket); |
| 358 | 268 | ||
| 359 | // this is here as a check (perhaps a different upper limit is good?) | 269 | /* this is here as a check (perhaps a different upper limit is good?) */ |
| 360 | if (entire_len > (uint32_t)MAXIMUM_PACKET_SIZE) { | 270 | if (entire_len > (uint32_t)MAXIMUM_PACKET_SIZE) { |
| 361 | fprintf(stderr, "%s: entire_len is larger than MAXIMUM_PACKET_SIZE, (%d > %d)!\n", __func__, entire_len, MAXIMUM_PACKET_SIZE); | 271 | fprintf(stderr, "%s: entire_len is larger than MAXIMUM_PACKET_SIZE, (%d > %d)!\n", __func__, entire_len, MAXIMUM_PACKET_SIZE); |
| 362 | } | 272 | } |
| 363 | 273 | ||
| 364 | *dump_here = (char*)malloc(entire_len); | 274 | *dump_here = (char*)malloc(entire_len); |
| 365 | if (this_len > 0) { | 275 | if (this_len > 0) { |
| 366 | usbmuxd_recv(client->sfd, *dump_here, this_len, (uint32_t*)&bytes); | 276 | usbmuxd_recv(client->sfd, *dump_here, this_len, (uint32_t*)bytes); |
| 367 | if (bytes <= 0) { | 277 | if (*bytes <= 0) { |
| 368 | free(*dump_here); | 278 | free(*dump_here); |
| 369 | *dump_here = NULL; | 279 | *dump_here = NULL; |
| 370 | log_debug_msg("%s: Did not get packet contents!\n", __func__); | 280 | log_debug_msg("%s: Did not get packet contents!\n", __func__); |
| 371 | return -1; | 281 | return AFC_E_NOT_ENOUGH_DATA; |
| 372 | } else if ((uint32_t)bytes < this_len) { | 282 | } else if ((uint32_t)*bytes < this_len) { |
| 373 | free(*dump_here); | 283 | free(*dump_here); |
| 374 | *dump_here = NULL; | 284 | *dump_here = NULL; |
| 375 | log_debug_msg("%s: Could not receive this_len=%d bytes\n", __func__, this_len); | 285 | log_debug_msg("%s: Could not receive this_len=%d bytes\n", __func__, this_len); |
| 376 | return -1; | 286 | return AFC_E_NOT_ENOUGH_DATA; |
| 377 | } | 287 | } |
| 378 | } | 288 | } |
| 379 | 289 | ||
| @@ -381,12 +291,12 @@ static int receive_AFC_data(afc_client_t client, char **dump_here) | |||
| 381 | 291 | ||
| 382 | if (entire_len > this_len) { | 292 | if (entire_len > this_len) { |
| 383 | while (current_count < entire_len) { | 293 | while (current_count < entire_len) { |
| 384 | usbmuxd_recv(client->sfd, (*dump_here)+current_count, entire_len - current_count, (uint32_t*)&bytes); | 294 | usbmuxd_recv(client->sfd, (*dump_here)+current_count, entire_len - current_count, (uint32_t*)bytes); |
| 385 | if (bytes <= 0) { | 295 | if (*bytes <= 0) { |
| 386 | log_debug_msg("%s: Error receiving data (recv returned %d)\n", __func__, bytes); | 296 | log_debug_msg("%s: Error receiving data (recv returned %d)\n", __func__, *bytes); |
| 387 | break; | 297 | break; |
| 388 | } | 298 | } |
| 389 | current_count += bytes; | 299 | current_count += *bytes; |
| 390 | } | 300 | } |
| 391 | if (current_count < entire_len) { | 301 | if (current_count < entire_len) { |
| 392 | log_debug_msg("%s: WARNING: could not receive full packet (read %s, size %d)\n", __func__, current_count, entire_len); | 302 | log_debug_msg("%s: WARNING: could not receive full packet (read %s, size %d)\n", __func__, current_count, entire_len); |
| @@ -397,39 +307,45 @@ static int receive_AFC_data(afc_client_t client, char **dump_here) | |||
| 397 | param1 = *(uint64_t*)(*dump_here); | 307 | param1 = *(uint64_t*)(*dump_here); |
| 398 | } | 308 | } |
| 399 | 309 | ||
| 400 | // check for errors | 310 | log_debug_msg("%s: packet data size = %i\n", __func__, current_count); |
| 401 | if (header.operation == AFC_SUCCESS_RESPONSE) { | 311 | log_debug_msg("%s: packet data follows\n", __func__); |
| 402 | // we got a positive response! | 312 | log_debug_buffer(*dump_here, current_count); |
| 403 | log_debug_msg("%s: got a success response\n", __func__); | 313 | |
| 404 | } else if (header.operation == AFC_FILE_HANDLE) { | 314 | /* check operation types */ |
| 405 | // we got a file handle response | 315 | if (header.operation == AFC_OP_STATUS) { |
| 406 | log_debug_msg("%s: got a file handle response, handle=%lld\n", __func__, param1); | 316 | /* status response */ |
| 407 | } else if (header.operation == AFC_ERROR) { | 317 | log_debug_msg("%s: got a status response, code=%lld\n", __func__, param1); |
| 408 | // error message received | 318 | |
| 409 | if (param1 == 0) { | 319 | if (param1 != AFC_E_SUCCESS) { |
| 410 | // ERROR_SUCCESS, this is not an error! | 320 | /* error status */ |
| 411 | log_debug_msg("%s: ERROR_SUCCESS\n", __func__); | 321 | /* free buffer */ |
| 412 | } else { | ||
| 413 | // but this is an error! | ||
| 414 | log_debug_msg("%s: ERROR %lld\n", __func__, param1); | ||
| 415 | free(*dump_here); | 322 | free(*dump_here); |
| 416 | *dump_here = NULL; | 323 | *dump_here = NULL; |
| 417 | // store error value | 324 | return (afc_error_t)param1; |
| 418 | client->afcerror = (int)param1; | ||
| 419 | afcerror_to_errno(client->afcerror); | ||
| 420 | return -1; | ||
| 421 | } | 325 | } |
| 326 | } else if (header.operation == AFC_OP_DATA) { | ||
| 327 | /* data response */ | ||
| 328 | log_debug_msg("%s: got a data response\n", __func__); | ||
| 329 | } else if (header.operation == AFC_OP_FILE_OPEN_RES) { | ||
| 330 | /* file handle response */ | ||
| 331 | log_debug_msg("%s: got a file handle response, handle=%lld\n", __func__, param1); | ||
| 332 | } else if (header.operation == AFC_OP_FILE_TELL_RES) { | ||
| 333 | /* tell response */ | ||
| 334 | log_debug_msg("%s: got a tell response, position=%lld\n", __func__, param1); | ||
| 422 | } else { | 335 | } else { |
| 423 | // unknown operation code received! | 336 | /* unknown operation code received */ |
| 424 | free(*dump_here); | 337 | free(*dump_here); |
| 425 | *dump_here = NULL; | 338 | *dump_here = NULL; |
| 339 | *bytes = 0; | ||
| 426 | 340 | ||
| 427 | log_debug_msg("%s: WARNING: Unknown operation code received 0x%llx param1=%lld\n", __func__, header.operation, param1); | 341 | log_debug_msg("%s: WARNING: Unknown operation code received 0x%llx param1=%lld\n", __func__, header.operation, param1); |
| 428 | fprintf(stderr, "%s: WARNING: Unknown operation code received 0x%llx param1=%lld\n", __func__, (long long)header.operation, (long long)param1); | 342 | fprintf(stderr, "%s: WARNING: Unknown operation code received 0x%llx param1=%lld\n", __func__, (long long)header.operation, (long long)param1); |
| 429 | 343 | ||
| 430 | return -1; | 344 | return AFC_E_OP_NOT_SUPPORTED; |
| 431 | } | 345 | } |
| 432 | return current_count; | 346 | |
| 347 | *bytes = current_count; | ||
| 348 | return AFC_E_SUCCESS; | ||
| 433 | } | 349 | } |
| 434 | 350 | ||
| 435 | static int count_nullspaces(char *string, int number) | 351 | static int count_nullspaces(char *string, int number) |
| @@ -471,36 +387,34 @@ static char **make_strings_list(char *tokens, int true_length) | |||
| 471 | * @return A char ** list of files in that directory, terminated by an empty | 387 | * @return A char ** list of files in that directory, terminated by an empty |
| 472 | * string for now or NULL if there was an error. | 388 | * string for now or NULL if there was an error. |
| 473 | */ | 389 | */ |
| 474 | iphone_error_t afc_get_dir_list(afc_client_t client, const char *dir, char ***list) | 390 | afc_error_t afc_read_directory(afc_client_t client, const char *dir, char ***list) |
| 475 | { | 391 | { |
| 476 | int bytes = 0; | 392 | int bytes = 0; |
| 477 | char *data = NULL, **list_loc = NULL; | 393 | char *data = NULL, **list_loc = NULL; |
| 478 | iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; | 394 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; |
| 479 | 395 | ||
| 480 | if (!client || !dir || !list || (list && *list)) | 396 | if (!client || !dir || !list || (list && *list)) |
| 481 | return IPHONE_E_INVALID_ARG; | 397 | return AFC_E_INVALID_ARGUMENT; |
| 482 | 398 | ||
| 483 | afc_lock(client); | 399 | afc_lock(client); |
| 484 | 400 | ||
| 485 | // Send the command | 401 | // Send the command |
| 486 | client->afc_packet->operation = AFC_LIST_DIR; | 402 | client->afc_packet->operation = AFC_OP_READ_DIR; |
| 487 | client->afc_packet->entire_length = 0; | 403 | client->afc_packet->entire_length = 0; |
| 488 | client->afc_packet->this_length = 0; | 404 | client->afc_packet->this_length = 0; |
| 489 | bytes = dispatch_AFC_packet(client, dir, strlen(dir)+1); | 405 | bytes = afc_dispatch_packet(client, dir, strlen(dir)+1); |
| 490 | if (bytes <= 0) { | 406 | if (bytes <= 0) { |
| 491 | afc_unlock(client); | 407 | afc_unlock(client); |
| 492 | return IPHONE_E_NOT_ENOUGH_DATA; | 408 | return AFC_E_NOT_ENOUGH_DATA; |
| 493 | } | 409 | } |
| 494 | // Receive the data | 410 | // Receive the data |
| 495 | bytes = receive_AFC_data(client, &data); | 411 | ret = afc_receive_data(client, &data, &bytes); |
| 496 | if (bytes < 0) { | 412 | if (ret != AFC_E_SUCCESS) { |
| 497 | afc_unlock(client); | 413 | afc_unlock(client); |
| 498 | return IPHONE_E_AFC_ERROR; | 414 | return ret; |
| 499 | } | 415 | } |
| 500 | // Parse the data | 416 | // Parse the data |
| 501 | list_loc = make_strings_list(data, bytes); | 417 | list_loc = make_strings_list(data, bytes); |
| 502 | if (list_loc) | ||
| 503 | ret = IPHONE_E_SUCCESS; | ||
| 504 | if (data) | 418 | if (data) |
| 505 | free(data); | 419 | free(data); |
| 506 | 420 | ||
| @@ -517,29 +431,30 @@ iphone_error_t afc_get_dir_list(afc_client_t client, const char *dir, char ***li | |||
| 517 | * @return A char ** list of parameters as given by AFC or NULL if there was an | 431 | * @return A char ** list of parameters as given by AFC or NULL if there was an |
| 518 | * error. | 432 | * error. |
| 519 | */ | 433 | */ |
| 520 | iphone_error_t afc_get_devinfo(afc_client_t client, char ***infos) | 434 | afc_error_t afc_get_device_info(afc_client_t client, char ***infos) |
| 521 | { | 435 | { |
| 522 | int bytes = 0; | 436 | int bytes = 0; |
| 523 | char *data = NULL, **list = NULL; | 437 | char *data = NULL, **list = NULL; |
| 438 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 524 | 439 | ||
| 525 | if (!client || !infos) | 440 | if (!client || !infos) |
| 526 | return IPHONE_E_INVALID_ARG; | 441 | return AFC_E_INVALID_ARGUMENT; |
| 527 | 442 | ||
| 528 | afc_lock(client); | 443 | afc_lock(client); |
| 529 | 444 | ||
| 530 | // Send the command | 445 | // Send the command |
| 531 | client->afc_packet->operation = AFC_GET_DEVINFO; | 446 | client->afc_packet->operation = AFC_OP_GET_DEVINFO; |
| 532 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 447 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 533 | bytes = dispatch_AFC_packet(client, NULL, 0); | 448 | bytes = afc_dispatch_packet(client, NULL, 0); |
| 534 | if (bytes < 0) { | 449 | if (bytes < 0) { |
| 535 | afc_unlock(client); | 450 | afc_unlock(client); |
| 536 | return IPHONE_E_NOT_ENOUGH_DATA; | 451 | return AFC_E_NOT_ENOUGH_DATA; |
| 537 | } | 452 | } |
| 538 | // Receive the data | 453 | // Receive the data |
| 539 | bytes = receive_AFC_data(client, &data); | 454 | ret = afc_receive_data(client, &data, &bytes); |
| 540 | if (bytes < 0) { | 455 | if (ret != AFC_E_SUCCESS) { |
| 541 | afc_unlock(client); | 456 | afc_unlock(client); |
| 542 | return IPHONE_E_AFC_ERROR; | 457 | return ret; |
| 543 | } | 458 | } |
| 544 | // Parse the data | 459 | // Parse the data |
| 545 | list = make_strings_list(data, bytes); | 460 | list = make_strings_list(data, bytes); |
| @@ -547,66 +462,67 @@ iphone_error_t afc_get_devinfo(afc_client_t client, char ***infos) | |||
| 547 | free(data); | 462 | free(data); |
| 548 | 463 | ||
| 549 | afc_unlock(client); | 464 | afc_unlock(client); |
| 465 | |||
| 550 | *infos = list; | 466 | *infos = list; |
| 551 | return IPHONE_E_SUCCESS; | 467 | |
| 468 | return ret; | ||
| 552 | } | 469 | } |
| 553 | 470 | ||
| 554 | /** Deletes a file. | 471 | /** Deletes a file or directory. |
| 555 | * | 472 | * |
| 556 | * @param client The client to have delete the file. | 473 | * @param client The client to use. |
| 557 | * @param path The file to delete. (must be a fully-qualified path) | 474 | * @param path The path to delete. (must be a fully-qualified path) |
| 558 | * | 475 | * |
| 559 | * @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG | 476 | * @return AFC_E_SUCCESS if everythong went well, AFC_E_INVALID_ARGUMENT |
| 560 | * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise. | 477 | * if arguments are NULL or invalid, AFC_E_NOT_ENOUGH_DATA otherwise. |
| 561 | */ | 478 | */ |
| 562 | iphone_error_t afc_delete_file(afc_client_t client, const char *path) | 479 | afc_error_t afc_remove_path(afc_client_t client, const char *path) |
| 563 | { | 480 | { |
| 564 | char *response = NULL; | 481 | char *response = NULL; |
| 565 | int bytes; | 482 | int bytes; |
| 483 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 566 | 484 | ||
| 567 | if (!client || !path || !client->afc_packet || client->sfd < 0) | 485 | if (!client || !path || !client->afc_packet || client->sfd < 0) |
| 568 | return IPHONE_E_INVALID_ARG; | 486 | return AFC_E_INVALID_ARGUMENT; |
| 569 | 487 | ||
| 570 | afc_lock(client); | 488 | afc_lock(client); |
| 571 | 489 | ||
| 572 | // Send command | 490 | // Send command |
| 573 | client->afc_packet->this_length = client->afc_packet->entire_length = 0; | 491 | client->afc_packet->this_length = client->afc_packet->entire_length = 0; |
| 574 | client->afc_packet->operation = AFC_DELETE; | 492 | client->afc_packet->operation = AFC_OP_REMOVE_PATH; |
| 575 | bytes = dispatch_AFC_packet(client, path, strlen(path)+1); | 493 | bytes = afc_dispatch_packet(client, path, strlen(path)+1); |
| 576 | if (bytes <= 0) { | 494 | if (bytes <= 0) { |
| 577 | afc_unlock(client); | 495 | afc_unlock(client); |
| 578 | return IPHONE_E_NOT_ENOUGH_DATA; | 496 | return AFC_E_NOT_ENOUGH_DATA; |
| 579 | } | 497 | } |
| 580 | // Receive response | 498 | // Receive response |
| 581 | bytes = receive_AFC_data(client, &response); | 499 | ret = afc_receive_data(client, &response, &bytes); |
| 582 | if (response) | 500 | if (response) |
| 583 | free(response); | 501 | free(response); |
| 584 | 502 | ||
| 585 | afc_unlock(client); | 503 | afc_unlock(client); |
| 586 | 504 | ||
| 587 | if (bytes < 0) { | 505 | return ret; |
| 588 | return IPHONE_E_AFC_ERROR; | ||
| 589 | } | ||
| 590 | return IPHONE_E_SUCCESS; | ||
| 591 | } | 506 | } |
| 592 | 507 | ||
| 593 | /** Renames a file on the phone. | 508 | /** Renames a file or directory on the phone. |
| 594 | * | 509 | * |
| 595 | * @param client The client to have rename the file. | 510 | * @param client The client to have rename. |
| 596 | * @param from The file to rename. (must be a fully-qualified path) | 511 | * @param from The name to rename from. (must be a fully-qualified path) |
| 597 | * @param to The new name of the file. (must also be a fully-qualified path) | 512 | * @param to The new name. (must also be a fully-qualified path) |
| 598 | * | 513 | * |
| 599 | * @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG | 514 | * @return AFC_E_SUCCESS if everythong went well, AFC_E_INVALID_ARGUMENT |
| 600 | * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise. | 515 | * if arguments are NULL or invalid, AFC_E_NOT_ENOUGH_DATA otherwise. |
| 601 | */ | 516 | */ |
| 602 | iphone_error_t afc_rename_file(afc_client_t client, const char *from, const char *to) | 517 | afc_error_t afc_rename_path(afc_client_t client, const char *from, const char *to) |
| 603 | { | 518 | { |
| 604 | char *response = NULL; | 519 | char *response = NULL; |
| 605 | char *send = (char *) malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32_t))); | 520 | char *send = (char *) malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32_t))); |
| 606 | int bytes = 0; | 521 | int bytes = 0; |
| 522 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 607 | 523 | ||
| 608 | if (!client || !from || !to || !client->afc_packet || client->sfd < 0) | 524 | if (!client || !from || !to || !client->afc_packet || client->sfd < 0) |
| 609 | return IPHONE_E_INVALID_ARG; | 525 | return AFC_E_INVALID_ARGUMENT; |
| 610 | 526 | ||
| 611 | afc_lock(client); | 527 | afc_lock(client); |
| 612 | 528 | ||
| @@ -614,24 +530,21 @@ iphone_error_t afc_rename_file(afc_client_t client, const char *from, const char | |||
| 614 | memcpy(send, from, strlen(from) + 1); | 530 | memcpy(send, from, strlen(from) + 1); |
| 615 | memcpy(send + strlen(from) + 1, to, strlen(to) + 1); | 531 | memcpy(send + strlen(from) + 1, to, strlen(to) + 1); |
| 616 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 532 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 617 | client->afc_packet->operation = AFC_RENAME; | 533 | client->afc_packet->operation = AFC_OP_RENAME_PATH; |
| 618 | bytes = dispatch_AFC_packet(client, send, strlen(to)+1 + strlen(from)+1); | 534 | bytes = afc_dispatch_packet(client, send, strlen(to)+1 + strlen(from)+1); |
| 619 | free(send); | 535 | free(send); |
| 620 | if (bytes <= 0) { | 536 | if (bytes <= 0) { |
| 621 | afc_unlock(client); | 537 | afc_unlock(client); |
| 622 | return IPHONE_E_NOT_ENOUGH_DATA; | 538 | return AFC_E_NOT_ENOUGH_DATA; |
| 623 | } | 539 | } |
| 624 | // Receive response | 540 | // Receive response |
| 625 | bytes = receive_AFC_data(client, &response); | 541 | ret = afc_receive_data(client, &response, &bytes); |
| 626 | if (response) | 542 | if (response) |
| 627 | free(response); | 543 | free(response); |
| 628 | 544 | ||
| 629 | afc_unlock(client); | 545 | afc_unlock(client); |
| 630 | 546 | ||
| 631 | if (bytes < 0) { | 547 | return ret; |
| 632 | return IPHONE_E_AFC_ERROR; | ||
| 633 | } | ||
| 634 | return IPHONE_E_SUCCESS; | ||
| 635 | } | 548 | } |
| 636 | 549 | ||
| 637 | /** Creates a directory on the phone. | 550 | /** Creates a directory on the phone. |
| @@ -640,38 +553,36 @@ iphone_error_t afc_rename_file(afc_client_t client, const char *from, const char | |||
| 640 | * @param dir The directory's path. (must be a fully-qualified path, I assume | 553 | * @param dir The directory's path. (must be a fully-qualified path, I assume |
| 641 | * all other mkdir restrictions apply as well) | 554 | * all other mkdir restrictions apply as well) |
| 642 | * | 555 | * |
| 643 | * @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG | 556 | * @return AFC_E_SUCCESS if everythong went well, AFC_E_INVALID_ARGUMENT |
| 644 | * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise. | 557 | * if arguments are NULL or invalid, AFC_E_NOT_ENOUGH_DATA otherwise. |
| 645 | */ | 558 | */ |
| 646 | iphone_error_t afc_mkdir(afc_client_t client, const char *dir) | 559 | afc_error_t afc_make_directory(afc_client_t client, const char *dir) |
| 647 | { | 560 | { |
| 648 | int bytes = 0; | 561 | int bytes = 0; |
| 649 | char *response = NULL; | 562 | char *response = NULL; |
| 563 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 650 | 564 | ||
| 651 | if (!client) | 565 | if (!client) |
| 652 | return IPHONE_E_INVALID_ARG; | 566 | return AFC_E_INVALID_ARGUMENT; |
| 653 | 567 | ||
| 654 | afc_lock(client); | 568 | afc_lock(client); |
| 655 | 569 | ||
| 656 | // Send command | 570 | // Send command |
| 657 | client->afc_packet->operation = AFC_MAKE_DIR; | 571 | client->afc_packet->operation = AFC_OP_MAKE_DIR; |
| 658 | client->afc_packet->this_length = client->afc_packet->entire_length = 0; | 572 | client->afc_packet->this_length = client->afc_packet->entire_length = 0; |
| 659 | bytes = dispatch_AFC_packet(client, dir, strlen(dir)+1); | 573 | bytes = afc_dispatch_packet(client, dir, strlen(dir)+1); |
| 660 | if (bytes <= 0) { | 574 | if (bytes <= 0) { |
| 661 | afc_unlock(client); | 575 | afc_unlock(client); |
| 662 | return IPHONE_E_NOT_ENOUGH_DATA; | 576 | return AFC_E_NOT_ENOUGH_DATA; |
| 663 | } | 577 | } |
| 664 | // Receive response | 578 | // Receive response |
| 665 | bytes = receive_AFC_data(client, &response); | 579 | ret = afc_receive_data(client, &response, &bytes); |
| 666 | if (response) | 580 | if (response) |
| 667 | free(response); | 581 | free(response); |
| 668 | 582 | ||
| 669 | afc_unlock(client); | 583 | afc_unlock(client); |
| 670 | 584 | ||
| 671 | if (bytes < 0) { | 585 | return ret; |
| 672 | return IPHONE_E_AFC_ERROR; | ||
| 673 | } | ||
| 674 | return IPHONE_E_SUCCESS; | ||
| 675 | } | 586 | } |
| 676 | 587 | ||
| 677 | /** Gets information about a specific file. | 588 | /** Gets information about a specific file. |
| @@ -682,38 +593,35 @@ iphone_error_t afc_mkdir(afc_client_t client, const char *dir) | |||
| 682 | * list of strings with the file information. | 593 | * list of strings with the file information. |
| 683 | * Set to NULL before calling this function. | 594 | * Set to NULL before calling this function. |
| 684 | * | 595 | * |
| 685 | * @return IPHONE_E_SUCCESS on success or an IPHONE_E_* error value | 596 | * @return AFC_E_SUCCESS on success or an AFC_E_* error value |
| 686 | * when something went wrong. | 597 | * when something went wrong. |
| 687 | */ | 598 | */ |
| 688 | iphone_error_t afc_get_file_info(afc_client_t client, const char *path, char ***infolist) | 599 | afc_error_t afc_get_file_info(afc_client_t client, const char *path, char ***infolist) |
| 689 | { | 600 | { |
| 690 | char *received = NULL; | 601 | char *received = NULL; |
| 691 | int length; | 602 | int bytes; |
| 603 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 692 | 604 | ||
| 693 | if (!client || !path || !infolist) { | 605 | if (!client || !path || !infolist) |
| 694 | return IPHONE_E_INVALID_ARG; | 606 | return AFC_E_INVALID_ARGUMENT; |
| 695 | } | ||
| 696 | 607 | ||
| 697 | afc_lock(client); | 608 | afc_lock(client); |
| 698 | 609 | ||
| 699 | // Send command | 610 | // Send command |
| 700 | client->afc_packet->operation = AFC_GET_INFO; | 611 | client->afc_packet->operation = AFC_OP_GET_FILE_INFO; |
| 701 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 612 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 702 | dispatch_AFC_packet(client, path, strlen(path)+1); | 613 | afc_dispatch_packet(client, path, strlen(path)+1); |
| 703 | 614 | ||
| 704 | // Receive data | 615 | // Receive data |
| 705 | length = receive_AFC_data(client, &received); | 616 | ret = afc_receive_data(client, &received, &bytes); |
| 706 | if (received) { | 617 | if (received) { |
| 707 | *infolist = make_strings_list(received, length); | 618 | *infolist = make_strings_list(received, bytes); |
| 708 | free(received); | 619 | free(received); |
| 709 | } else { | ||
| 710 | afc_unlock(client); | ||
| 711 | return IPHONE_E_AFC_ERROR; | ||
| 712 | } | 620 | } |
| 713 | 621 | ||
| 714 | afc_unlock(client); | 622 | afc_unlock(client); |
| 715 | 623 | ||
| 716 | return IPHONE_E_SUCCESS; | 624 | return ret; |
| 717 | } | 625 | } |
| 718 | 626 | ||
| 719 | /** Opens a file on the phone. | 627 | /** Opens a file on the phone. |
| @@ -726,21 +634,22 @@ iphone_error_t afc_get_file_info(afc_client_t client, const char *path, char *** | |||
| 726 | * destroying anything previously there. | 634 | * destroying anything previously there. |
| 727 | * @param handle Pointer to a uint64_t that will hold the handle of the file | 635 | * @param handle Pointer to a uint64_t that will hold the handle of the file |
| 728 | * | 636 | * |
| 729 | * @return IPHONE_E_SUCCESS on success or an IPHONE_E_* error on failure. | 637 | * @return AFC_E_SUCCESS on success or an AFC_E_* error on failure. |
| 730 | */ | 638 | */ |
| 731 | iphone_error_t | 639 | iphone_error_t |
| 732 | afc_open_file(afc_client_t client, const char *filename, | 640 | afc_file_open(afc_client_t client, const char *filename, |
| 733 | afc_file_mode_t file_mode, uint64_t *handle) | 641 | afc_file_mode_t file_mode, uint64_t *handle) |
| 734 | { | 642 | { |
| 735 | uint32_t ag = 0; | 643 | uint32_t ag = 0; |
| 736 | int bytes = 0, length = 0; | 644 | int bytes = 0; |
| 737 | char *data = (char *) malloc(sizeof(char) * (8 + strlen(filename) + 1)); | 645 | char *data = (char *) malloc(sizeof(char) * (8 + strlen(filename) + 1)); |
| 646 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 738 | 647 | ||
| 739 | // set handle to 0 so in case an error occurs, the handle is invalid | 648 | // set handle to 0 so in case an error occurs, the handle is invalid |
| 740 | *handle = 0; | 649 | *handle = 0; |
| 741 | 650 | ||
| 742 | if (!client || client->sfd < 0|| !client->afc_packet) | 651 | if (!client || client->sfd < 0|| !client->afc_packet) |
| 743 | return IPHONE_E_INVALID_ARG; | 652 | return AFC_E_INVALID_ARGUMENT; |
| 744 | 653 | ||
| 745 | afc_lock(client); | 654 | afc_lock(client); |
| 746 | 655 | ||
| @@ -749,34 +658,32 @@ afc_open_file(afc_client_t client, const char *filename, | |||
| 749 | memcpy(data + 4, &ag, 4); | 658 | memcpy(data + 4, &ag, 4); |
| 750 | memcpy(data + 8, filename, strlen(filename)); | 659 | memcpy(data + 8, filename, strlen(filename)); |
| 751 | data[8 + strlen(filename)] = '\0'; | 660 | data[8 + strlen(filename)] = '\0'; |
| 752 | client->afc_packet->operation = AFC_FILE_OPEN; | 661 | client->afc_packet->operation = AFC_OP_FILE_OPEN; |
| 753 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 662 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 754 | bytes = dispatch_AFC_packet(client, data, 8 + strlen(filename) + 1); | 663 | bytes = afc_dispatch_packet(client, data, 8 + strlen(filename) + 1); |
| 755 | free(data); | 664 | free(data); |
| 756 | 665 | ||
| 757 | if (bytes <= 0) { | 666 | if (bytes <= 0) { |
| 758 | log_debug_msg("afc_open_file: Didn't receive a response to the command\n"); | 667 | log_debug_msg("%s: Didn't receive a response to the command\n", __func__); |
| 759 | afc_unlock(client); | 668 | afc_unlock(client); |
| 760 | return IPHONE_E_NOT_ENOUGH_DATA; | 669 | return AFC_E_NOT_ENOUGH_DATA; |
| 761 | } | 670 | } |
| 762 | // Receive the data | 671 | // Receive the data |
| 763 | length = receive_AFC_data(client, &data); | 672 | ret = afc_receive_data(client, &data, &bytes); |
| 764 | if (length > 0 && data) { | 673 | if ((ret == AFC_E_SUCCESS) && (bytes > 0) && data) { |
| 765 | afc_unlock(client); | 674 | afc_unlock(client); |
| 766 | 675 | ||
| 767 | // Get the file handle | 676 | // Get the file handle |
| 768 | memcpy(handle, data, sizeof(uint64_t)); | 677 | memcpy(handle, data, sizeof(uint64_t)); |
| 769 | free(data); | 678 | free(data); |
| 770 | return IPHONE_E_SUCCESS; | 679 | return ret; |
| 771 | } else { | ||
| 772 | log_debug_msg("afc_open_file: Didn't get any further data\n"); | ||
| 773 | afc_unlock(client); | ||
| 774 | return IPHONE_E_AFC_ERROR; | ||
| 775 | } | 680 | } |
| 776 | 681 | ||
| 682 | log_debug_msg("%s: Didn't get any further data\n", __func__); | ||
| 683 | |||
| 777 | afc_unlock(client); | 684 | afc_unlock(client); |
| 778 | 685 | ||
| 779 | return IPHONE_E_UNKNOWN_ERROR; | 686 | return ret; |
| 780 | } | 687 | } |
| 781 | 688 | ||
| 782 | /** Attempts to the read the given number of bytes from the given file. | 689 | /** Attempts to the read the given number of bytes from the given file. |
| @@ -789,52 +696,54 @@ afc_open_file(afc_client_t client, const char *filename, | |||
| 789 | * @return The number of bytes read if successful. If there was an error -1. | 696 | * @return The number of bytes read if successful. If there was an error -1. |
| 790 | */ | 697 | */ |
| 791 | iphone_error_t | 698 | iphone_error_t |
| 792 | afc_read_file(afc_client_t client, uint64_t handle, char *data, int length, uint32_t * bytes) | 699 | afc_file_read(afc_client_t client, uint64_t handle, char *data, int length, uint32_t * bytes) |
| 793 | { | 700 | { |
| 794 | char *input = NULL; | 701 | char *input = NULL; |
| 795 | int current_count = 0, bytes_loc = 0; | 702 | int current_count = 0, bytes_loc = 0; |
| 796 | const int MAXIMUM_READ_SIZE = 1 << 16; | 703 | const int MAXIMUM_READ_SIZE = 1 << 16; |
| 704 | afc_error_t ret = AFC_E_SUCCESS; | ||
| 797 | 705 | ||
| 798 | if (!client || !client->afc_packet || client->sfd < 0 || handle == 0) | 706 | if (!client || !client->afc_packet || client->sfd < 0 || handle == 0) |
| 799 | return IPHONE_E_INVALID_ARG; | 707 | return AFC_E_INVALID_ARGUMENT; |
| 800 | log_debug_msg("afc_read_file called for length %i\n", length); | 708 | log_debug_msg("%s: called for length %i\n", __func__, length); |
| 801 | 709 | ||
| 802 | afc_lock(client); | 710 | afc_lock(client); |
| 803 | 711 | ||
| 804 | // Looping here to get around the maximum amount of data that | 712 | // Looping here to get around the maximum amount of data that |
| 805 | // recieve_AFC_data can handle | 713 | // afc_receive_data can handle |
| 806 | while (current_count < length) { | 714 | while (current_count < length) { |
| 807 | log_debug_msg("afc_read_file: current count is %i but length is %i\n", current_count, length); | 715 | log_debug_msg("%s: current count is %i but length is %i\n", __func__, current_count, length); |
| 808 | 716 | ||
| 809 | // Send the read command | 717 | // Send the read command |
| 810 | AFCFilePacket *packet = (AFCFilePacket *) malloc(sizeof(AFCFilePacket)); | 718 | AFCFilePacket *packet = (AFCFilePacket *) malloc(sizeof(AFCFilePacket)); |
| 811 | packet->filehandle = handle; | 719 | packet->filehandle = handle; |
| 812 | packet->size = ((length - current_count) < MAXIMUM_READ_SIZE) ? (length - current_count) : MAXIMUM_READ_SIZE; | 720 | packet->size = ((length - current_count) < MAXIMUM_READ_SIZE) ? (length - current_count) : MAXIMUM_READ_SIZE; |
| 813 | client->afc_packet->operation = AFC_READ; | 721 | client->afc_packet->operation = AFC_OP_READ; |
| 814 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 722 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 815 | bytes_loc = dispatch_AFC_packet(client, (char *) packet, sizeof(AFCFilePacket)); | 723 | bytes_loc = afc_dispatch_packet(client, (char *) packet, sizeof(AFCFilePacket)); |
| 816 | free(packet); | 724 | free(packet); |
| 817 | 725 | ||
| 818 | if (bytes_loc <= 0) { | 726 | if (bytes_loc <= 0) { |
| 819 | afc_unlock(client); | 727 | afc_unlock(client); |
| 820 | return IPHONE_E_NOT_ENOUGH_DATA; | 728 | return AFC_E_NOT_ENOUGH_DATA; |
| 821 | } | 729 | } |
| 822 | // Receive the data | 730 | // Receive the data |
| 823 | bytes_loc = receive_AFC_data(client, &input); | 731 | ret = afc_receive_data(client, &input, &bytes_loc); |
| 824 | log_debug_msg("afc_read_file: bytes returned: %i\n", bytes_loc); | 732 | log_debug_msg("%s: afc_receive_data returned error: %d\n", __func__, ret); |
| 825 | if (bytes_loc < 0) { | 733 | log_debug_msg("%s: bytes returned: %i\n", __func__, bytes_loc); |
| 734 | if (ret != AFC_E_SUCCESS) { | ||
| 826 | afc_unlock(client); | 735 | afc_unlock(client); |
| 827 | return IPHONE_E_AFC_ERROR; | 736 | return ret; |
| 828 | } else if (bytes_loc == 0) { | 737 | } else if (bytes_loc == 0) { |
| 829 | if (input) | 738 | if (input) |
| 830 | free(input); | 739 | free(input); |
| 831 | afc_unlock(client); | 740 | afc_unlock(client); |
| 832 | *bytes = current_count; | 741 | *bytes = current_count; |
| 833 | return IPHONE_E_SUCCESS; // FIXME check that's actually a | 742 | /* FIXME: check that's actually a success */ |
| 834 | // success | 743 | return ret; |
| 835 | } else { | 744 | } else { |
| 836 | if (input) { | 745 | if (input) { |
| 837 | log_debug_msg("afc_read_file: %d\n", bytes_loc); | 746 | log_debug_msg("%s: %d\n", __func__, bytes_loc); |
| 838 | memcpy(data + current_count, input, (bytes_loc > length) ? length : bytes_loc); | 747 | memcpy(data + current_count, input, (bytes_loc > length) ? length : bytes_loc); |
| 839 | free(input); | 748 | free(input); |
| 840 | input = NULL; | 749 | input = NULL; |
| @@ -842,11 +751,11 @@ afc_read_file(afc_client_t client, uint64_t handle, char *data, int length, uint | |||
| 842 | } | 751 | } |
| 843 | } | 752 | } |
| 844 | } | 753 | } |
| 845 | log_debug_msg("afc_read_file: returning current_count as %i\n", current_count); | 754 | log_debug_msg("%s: returning current_count as %i\n", __func__, current_count); |
| 846 | 755 | ||
| 847 | afc_unlock(client); | 756 | afc_unlock(client); |
| 848 | *bytes = current_count; | 757 | *bytes = current_count; |
| 849 | return IPHONE_E_SUCCESS; | 758 | return ret; |
| 850 | } | 759 | } |
| 851 | 760 | ||
| 852 | /** Writes a given number of bytes to a file. | 761 | /** Writes a given number of bytes to a file. |
| @@ -860,7 +769,7 @@ afc_read_file(afc_client_t client, uint64_t handle, char *data, int length, uint | |||
| 860 | * none were written... | 769 | * none were written... |
| 861 | */ | 770 | */ |
| 862 | iphone_error_t | 771 | iphone_error_t |
| 863 | afc_write_file(afc_client_t client, uint64_t handle, | 772 | afc_file_write(afc_client_t client, uint64_t handle, |
| 864 | const char *data, int length, uint32_t * bytes) | 773 | const char *data, int length, uint32_t * bytes) |
| 865 | { | 774 | { |
| 866 | char *acknowledgement = NULL; | 775 | char *acknowledgement = NULL; |
| @@ -869,36 +778,37 @@ afc_write_file(afc_client_t client, uint64_t handle, | |||
| 869 | uint32_t segments = (length / MAXIMUM_WRITE_SIZE); | 778 | uint32_t segments = (length / MAXIMUM_WRITE_SIZE); |
| 870 | int bytes_loc = 0; | 779 | int bytes_loc = 0; |
| 871 | char *out_buffer = NULL; | 780 | char *out_buffer = NULL; |
| 781 | afc_error_t ret = AFC_E_SUCCESS; | ||
| 872 | 782 | ||
| 873 | if (!client || !client->afc_packet || client->sfd < 0 || !bytes || (handle == 0)) | 783 | if (!client || !client->afc_packet || client->sfd < 0 || !bytes || (handle == 0)) |
| 874 | return IPHONE_E_INVALID_ARG; | 784 | return AFC_E_INVALID_ARGUMENT; |
| 875 | 785 | ||
| 876 | afc_lock(client); | 786 | afc_lock(client); |
| 877 | 787 | ||
| 878 | log_debug_msg("afc_write_file: Write length: %i\n", length); | 788 | log_debug_msg("%s: Write length: %i\n", __func__, length); |
| 879 | 789 | ||
| 880 | // Divide the file into segments. | 790 | // Divide the file into segments. |
| 881 | for (i = 0; i < segments; i++) { | 791 | for (i = 0; i < segments; i++) { |
| 882 | // Send the segment | 792 | // Send the segment |
| 883 | client->afc_packet->this_length = sizeof(AFCPacket) + 8; | 793 | client->afc_packet->this_length = sizeof(AFCPacket) + 8; |
| 884 | client->afc_packet->entire_length = client->afc_packet->this_length + MAXIMUM_WRITE_SIZE; | 794 | client->afc_packet->entire_length = client->afc_packet->this_length + MAXIMUM_WRITE_SIZE; |
| 885 | client->afc_packet->operation = AFC_WRITE; | 795 | client->afc_packet->operation = AFC_OP_WRITE; |
| 886 | out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket)); | 796 | out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket)); |
| 887 | memcpy(out_buffer, (char *)&handle, sizeof(uint64_t)); | 797 | memcpy(out_buffer, (char *)&handle, sizeof(uint64_t)); |
| 888 | memcpy(out_buffer + 8, data + current_count, MAXIMUM_WRITE_SIZE); | 798 | memcpy(out_buffer + 8, data + current_count, MAXIMUM_WRITE_SIZE); |
| 889 | bytes_loc = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8); | 799 | bytes_loc = afc_dispatch_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8); |
| 890 | if (bytes_loc < 0) { | 800 | if (bytes_loc < 0) { |
| 891 | afc_unlock(client); | 801 | afc_unlock(client); |
| 892 | return IPHONE_E_NOT_ENOUGH_DATA; | 802 | return AFC_E_NOT_ENOUGH_DATA; |
| 893 | } | 803 | } |
| 894 | free(out_buffer); | 804 | free(out_buffer); |
| 895 | out_buffer = NULL; | 805 | out_buffer = NULL; |
| 896 | 806 | ||
| 897 | current_count += bytes_loc; | 807 | current_count += bytes_loc; |
| 898 | bytes_loc = receive_AFC_data(client, &acknowledgement); | 808 | ret = afc_receive_data(client, &acknowledgement, &bytes_loc); |
| 899 | if (bytes_loc < 0) { | 809 | if (ret != AFC_E_SUCCESS) { |
| 900 | afc_unlock(client); | 810 | afc_unlock(client); |
| 901 | return IPHONE_E_AFC_ERROR; | 811 | return ret; |
| 902 | } else { | 812 | } else { |
| 903 | free(acknowledgement); | 813 | free(acknowledgement); |
| 904 | } | 814 | } |
| @@ -911,16 +821,16 @@ afc_write_file(afc_client_t client, uint64_t handle, | |||
| 911 | if (current_count == (uint32_t)length) { | 821 | if (current_count == (uint32_t)length) { |
| 912 | afc_unlock(client); | 822 | afc_unlock(client); |
| 913 | *bytes = current_count; | 823 | *bytes = current_count; |
| 914 | return IPHONE_E_SUCCESS; | 824 | return ret; |
| 915 | } | 825 | } |
| 916 | 826 | ||
| 917 | client->afc_packet->this_length = sizeof(AFCPacket) + 8; | 827 | client->afc_packet->this_length = sizeof(AFCPacket) + 8; |
| 918 | client->afc_packet->entire_length = client->afc_packet->this_length + (length - current_count); | 828 | client->afc_packet->entire_length = client->afc_packet->this_length + (length - current_count); |
| 919 | client->afc_packet->operation = AFC_WRITE; | 829 | client->afc_packet->operation = AFC_OP_WRITE; |
| 920 | out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket)); | 830 | out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket)); |
| 921 | memcpy(out_buffer, (char *) &handle, sizeof(uint64_t)); | 831 | memcpy(out_buffer, (char *) &handle, sizeof(uint64_t)); |
| 922 | memcpy(out_buffer + 8, data + current_count, (length - current_count)); | 832 | memcpy(out_buffer + 8, data + current_count, (length - current_count)); |
| 923 | bytes_loc = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8); | 833 | bytes_loc = afc_dispatch_packet(client, out_buffer, (length - current_count) + 8); |
| 924 | free(out_buffer); | 834 | free(out_buffer); |
| 925 | out_buffer = NULL; | 835 | out_buffer = NULL; |
| 926 | 836 | ||
| @@ -929,19 +839,19 @@ afc_write_file(afc_client_t client, uint64_t handle, | |||
| 929 | if (bytes_loc <= 0) { | 839 | if (bytes_loc <= 0) { |
| 930 | afc_unlock(client); | 840 | afc_unlock(client); |
| 931 | *bytes = current_count; | 841 | *bytes = current_count; |
| 932 | return IPHONE_E_SUCCESS; | 842 | return AFC_E_SUCCESS; |
| 933 | } | 843 | } |
| 934 | 844 | ||
| 935 | zero = bytes_loc; | 845 | zero = bytes_loc; |
| 936 | bytes_loc = receive_AFC_data(client, &acknowledgement); | 846 | ret = afc_receive_data(client, &acknowledgement, &bytes_loc); |
| 937 | afc_unlock(client); | 847 | afc_unlock(client); |
| 938 | if (bytes_loc < 0) { | 848 | if (ret != AFC_E_SUCCESS) { |
| 939 | log_debug_msg("afc_write_file: uh oh?\n"); | 849 | log_debug_msg("%s: uh oh?\n", __func__); |
| 940 | } else { | 850 | } else { |
| 941 | free(acknowledgement); | 851 | free(acknowledgement); |
| 942 | } | 852 | } |
| 943 | *bytes = current_count; | 853 | *bytes = current_count; |
| 944 | return IPHONE_E_SUCCESS; | 854 | return ret; |
| 945 | } | 855 | } |
| 946 | 856 | ||
| 947 | /** Closes a file on the phone. | 857 | /** Closes a file on the phone. |
| @@ -949,95 +859,91 @@ afc_write_file(afc_client_t client, uint64_t handle, | |||
| 949 | * @param client The client to close the file with. | 859 | * @param client The client to close the file with. |
| 950 | * @param handle File handle of a previously opened file. | 860 | * @param handle File handle of a previously opened file. |
| 951 | */ | 861 | */ |
| 952 | iphone_error_t afc_close_file(afc_client_t client, uint64_t handle) | 862 | afc_error_t afc_file_close(afc_client_t client, uint64_t handle) |
| 953 | { | 863 | { |
| 954 | if (!client || (handle == 0)) | ||
| 955 | return IPHONE_E_INVALID_ARG; | ||
| 956 | char *buffer = malloc(sizeof(char) * 8); | 864 | char *buffer = malloc(sizeof(char) * 8); |
| 957 | int bytes = 0; | 865 | int bytes = 0; |
| 866 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 867 | |||
| 868 | if (!client || (handle == 0)) | ||
| 869 | return AFC_E_INVALID_ARGUMENT; | ||
| 958 | 870 | ||
| 959 | afc_lock(client); | 871 | afc_lock(client); |
| 960 | 872 | ||
| 961 | log_debug_msg("afc_close_file: File handle %i\n", handle); | 873 | log_debug_msg("%s: File handle %i\n", __func__, handle); |
| 962 | 874 | ||
| 963 | // Send command | 875 | // Send command |
| 964 | memcpy(buffer, &handle, sizeof(uint64_t)); | 876 | memcpy(buffer, &handle, sizeof(uint64_t)); |
| 965 | client->afc_packet->operation = AFC_FILE_CLOSE; | 877 | client->afc_packet->operation = AFC_OP_FILE_CLOSE; |
| 966 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 878 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 967 | bytes = dispatch_AFC_packet(client, buffer, 8); | 879 | bytes = afc_dispatch_packet(client, buffer, 8); |
| 968 | free(buffer); | 880 | free(buffer); |
| 969 | buffer = NULL; | 881 | buffer = NULL; |
| 970 | 882 | ||
| 971 | // FIXME: Is this necesary? | ||
| 972 | // client->afc_packet->entire_length = client->afc_packet->this_length | ||
| 973 | // = 0; | ||
| 974 | |||
| 975 | if (bytes <= 0) { | 883 | if (bytes <= 0) { |
| 976 | afc_unlock(client); | 884 | afc_unlock(client); |
| 977 | return IPHONE_E_UNKNOWN_ERROR; | 885 | return AFC_E_UNKNOWN_ERROR; |
| 978 | } | 886 | } |
| 887 | |||
| 979 | // Receive the response | 888 | // Receive the response |
| 980 | bytes = receive_AFC_data(client, &buffer); | 889 | ret = afc_receive_data(client, &buffer, &bytes); |
| 981 | if (buffer) | 890 | if (buffer) |
| 982 | free(buffer); | 891 | free(buffer); |
| 892 | |||
| 983 | afc_unlock(client); | 893 | afc_unlock(client); |
| 984 | return IPHONE_E_SUCCESS; | 894 | |
| 895 | return ret; | ||
| 985 | } | 896 | } |
| 986 | 897 | ||
| 987 | /** Locks or unlocks a file on the phone. | 898 | /** Locks or unlocks a file on the phone. |
| 988 | * | 899 | * |
| 989 | * makes use of flock, see | 900 | * makes use of flock on the device, see |
| 990 | * http://developer.apple.com/documentation/Darwin/Reference/ManPages/man2/flock.2.html | 901 | * http://developer.apple.com/documentation/Darwin/Reference/ManPages/man2/flock.2.html |
| 991 | * | 902 | * |
| 992 | * operation (same as in sys/file.h on linux): | 903 | * @param client The client to lock the file with. |
| 993 | * | ||
| 994 | * LOCK_SH 1 // shared lock | ||
| 995 | * LOCK_EX 2 // exclusive lock | ||
| 996 | * LOCK_NB 4 // don't block when locking | ||
| 997 | * LOCK_UN 8 // unlock | ||
| 998 | * | ||
| 999 | * @param client The client to close the file with. | ||
| 1000 | * @param handle File handle of a previously opened file. | 904 | * @param handle File handle of a previously opened file. |
| 1001 | * @operation the lock or unlock operation to perform. | 905 | * @param operation the lock or unlock operation to perform, this is one of |
| 906 | * AFC_LOCK_SH (shared lock), AFC_LOCK_EX (exclusive lock), | ||
| 907 | * or AFC_LOCK_UN (unlock). | ||
| 1002 | */ | 908 | */ |
| 1003 | iphone_error_t afc_lock_file(afc_client_t client, uint64_t handle, int operation) | 909 | afc_error_t afc_file_lock(afc_client_t client, uint64_t handle, afc_lock_op_t operation) |
| 1004 | { | 910 | { |
| 1005 | if (!client || (handle == 0)) | ||
| 1006 | return IPHONE_E_INVALID_ARG; | ||
| 1007 | char *buffer = malloc(16); | 911 | char *buffer = malloc(16); |
| 1008 | int bytes = 0; | 912 | int bytes = 0; |
| 1009 | uint64_t op = operation; | 913 | uint64_t op = operation; |
| 914 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 915 | |||
| 916 | if (!client || (handle == 0)) | ||
| 917 | return AFC_E_INVALID_ARGUMENT; | ||
| 1010 | 918 | ||
| 1011 | afc_lock(client); | 919 | afc_lock(client); |
| 1012 | 920 | ||
| 1013 | log_debug_msg("afc_lock_file: File handle %i\n", handle); | 921 | log_debug_msg("%s: file handle %i\n", __func__, handle); |
| 1014 | 922 | ||
| 1015 | // Send command | 923 | // Send command |
| 1016 | memcpy(buffer, &handle, sizeof(uint64_t)); | 924 | memcpy(buffer, &handle, sizeof(uint64_t)); |
| 1017 | memcpy(buffer + 8, &op, 8); | 925 | memcpy(buffer + 8, &op, 8); |
| 1018 | 926 | ||
| 1019 | client->afc_packet->operation = AFC_FILE_LOCK; | 927 | client->afc_packet->operation = AFC_OP_FILE_LOCK; |
| 1020 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 928 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 1021 | bytes = dispatch_AFC_packet(client, buffer, 16); | 929 | bytes = afc_dispatch_packet(client, buffer, 16); |
| 1022 | free(buffer); | 930 | free(buffer); |
| 1023 | buffer = NULL; | 931 | buffer = NULL; |
| 1024 | 932 | ||
| 1025 | if (bytes <= 0) { | 933 | if (bytes <= 0) { |
| 1026 | afc_unlock(client); | 934 | afc_unlock(client); |
| 1027 | log_debug_msg("fuck\n"); | 935 | log_debug_msg("%s: could not send lock command\n", __func__); |
| 1028 | return IPHONE_E_UNKNOWN_ERROR; | 936 | return AFC_E_UNKNOWN_ERROR; |
| 1029 | } | 937 | } |
| 1030 | // Receive the response | 938 | // Receive the response |
| 1031 | bytes = receive_AFC_data(client, &buffer); | 939 | ret = afc_receive_data(client, &buffer, &bytes); |
| 1032 | if (buffer) { | 940 | if (buffer) { |
| 1033 | log_debug_buffer(buffer, bytes); | 941 | log_debug_buffer(buffer, bytes); |
| 1034 | free(buffer); | 942 | free(buffer); |
| 1035 | } | 943 | } |
| 1036 | afc_unlock(client); | 944 | afc_unlock(client); |
| 1037 | if (bytes < 0) { | 945 | |
| 1038 | return IPHONE_E_AFC_ERROR; | 946 | return ret; |
| 1039 | } | ||
| 1040 | return IPHONE_E_SUCCESS; | ||
| 1041 | } | 947 | } |
| 1042 | 948 | ||
| 1043 | /** Seeks to a given position of a pre-opened file on the phone. | 949 | /** Seeks to a given position of a pre-opened file on the phone. |
| @@ -1047,13 +953,17 @@ iphone_error_t afc_lock_file(afc_client_t client, uint64_t handle, int operation | |||
| 1047 | * @param offset Seek offset. | 953 | * @param offset Seek offset. |
| 1048 | * @param whence Seeking direction, one of SEEK_SET, SEEK_CUR, or SEEK_END. | 954 | * @param whence Seeking direction, one of SEEK_SET, SEEK_CUR, or SEEK_END. |
| 1049 | * | 955 | * |
| 1050 | * @return IPHONE_E_SUCCESS on success, IPHONE_E_NOT_ENOUGH_DATA on failure. | 956 | * @return AFC_E_SUCCESS on success, AFC_E_NOT_ENOUGH_DATA on failure. |
| 1051 | */ | 957 | */ |
| 1052 | iphone_error_t afc_seek_file(afc_client_t client, uint64_t handle, int64_t offset, int whence) | 958 | afc_error_t afc_file_seek(afc_client_t client, uint64_t handle, int64_t offset, int whence) |
| 1053 | { | 959 | { |
| 1054 | char *buffer = (char *) malloc(sizeof(char) * 24); | 960 | char *buffer = (char *) malloc(sizeof(char) * 24); |
| 1055 | uint32_t zero = 0; | 961 | uint32_t zero = 0; |
| 1056 | int bytes = 0; | 962 | int bytes = 0; |
| 963 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 964 | |||
| 965 | if (!client || (handle == 0)) | ||
| 966 | return AFC_E_INVALID_ARGUMENT; | ||
| 1057 | 967 | ||
| 1058 | afc_lock(client); | 968 | afc_lock(client); |
| 1059 | 969 | ||
| @@ -1062,27 +972,70 @@ iphone_error_t afc_seek_file(afc_client_t client, uint64_t handle, int64_t offse | |||
| 1062 | memcpy(buffer + 8, &whence, sizeof(int32_t)); // fromwhere | 972 | memcpy(buffer + 8, &whence, sizeof(int32_t)); // fromwhere |
| 1063 | memcpy(buffer + 12, &zero, sizeof(uint32_t)); // pad | 973 | memcpy(buffer + 12, &zero, sizeof(uint32_t)); // pad |
| 1064 | memcpy(buffer + 16, &offset, sizeof(uint64_t)); // offset | 974 | memcpy(buffer + 16, &offset, sizeof(uint64_t)); // offset |
| 1065 | client->afc_packet->operation = AFC_FILE_SEEK; | 975 | client->afc_packet->operation = AFC_OP_FILE_SEEK; |
| 1066 | client->afc_packet->this_length = client->afc_packet->entire_length = 0; | 976 | client->afc_packet->this_length = client->afc_packet->entire_length = 0; |
| 1067 | bytes = dispatch_AFC_packet(client, buffer, 24); | 977 | bytes = afc_dispatch_packet(client, buffer, 24); |
| 1068 | free(buffer); | 978 | free(buffer); |
| 1069 | buffer = NULL; | 979 | buffer = NULL; |
| 1070 | 980 | ||
| 1071 | if (bytes <= 0) { | 981 | if (bytes <= 0) { |
| 1072 | afc_unlock(client); | 982 | afc_unlock(client); |
| 1073 | return IPHONE_E_NOT_ENOUGH_DATA; | 983 | return AFC_E_NOT_ENOUGH_DATA; |
| 1074 | } | 984 | } |
| 1075 | // Receive response | 985 | // Receive response |
| 1076 | bytes = receive_AFC_data(client, &buffer); | 986 | ret = afc_receive_data(client, &buffer, &bytes); |
| 1077 | if (buffer) | 987 | if (buffer) |
| 1078 | free(buffer); | 988 | free(buffer); |
| 1079 | 989 | ||
| 1080 | afc_unlock(client); | 990 | afc_unlock(client); |
| 1081 | 991 | ||
| 1082 | if (bytes < 0) { | 992 | return ret; |
| 1083 | return IPHONE_E_AFC_ERROR; | 993 | } |
| 994 | |||
| 995 | /** Returns current position in a pre-opened file on the phone. | ||
| 996 | * | ||
| 997 | * @param client The client to use. | ||
| 998 | * @param handle File handle of a previously opened file. | ||
| 999 | * @param position Position in bytes of indicator | ||
| 1000 | * | ||
| 1001 | * @return AFC_E_SUCCESS on success, AFC_E_NOT_ENOUGH_DATA on failure. | ||
| 1002 | */ | ||
| 1003 | afc_error_t afc_file_tell(afc_client_t client, uint64_t handle, uint64_t *position) | ||
| 1004 | { | ||
| 1005 | char *buffer = (char *) malloc(sizeof(char) * 8); | ||
| 1006 | int bytes = 0; | ||
| 1007 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 1008 | |||
| 1009 | if (!client || (handle == 0)) | ||
| 1010 | return AFC_E_INVALID_ARGUMENT; | ||
| 1011 | |||
| 1012 | afc_lock(client); | ||
| 1013 | |||
| 1014 | // Send the command | ||
| 1015 | memcpy(buffer, &handle, sizeof(uint64_t)); // handle | ||
| 1016 | client->afc_packet->operation = AFC_OP_FILE_TELL; | ||
| 1017 | client->afc_packet->this_length = client->afc_packet->entire_length = 0; | ||
| 1018 | bytes = afc_dispatch_packet(client, buffer, 8); | ||
| 1019 | free(buffer); | ||
| 1020 | buffer = NULL; | ||
| 1021 | |||
| 1022 | if (bytes <= 0) { | ||
| 1023 | afc_unlock(client); | ||
| 1024 | return AFC_E_NOT_ENOUGH_DATA; | ||
| 1084 | } | 1025 | } |
| 1085 | return IPHONE_E_SUCCESS; | 1026 | |
| 1027 | // Receive the data | ||
| 1028 | ret = afc_receive_data(client, &buffer, &bytes); | ||
| 1029 | if (bytes > 0 && buffer) { | ||
| 1030 | /* Get the position */ | ||
| 1031 | memcpy(position, buffer, sizeof(uint64_t)); | ||
| 1032 | } | ||
| 1033 | if (buffer) | ||
| 1034 | free(buffer); | ||
| 1035 | |||
| 1036 | afc_unlock(client); | ||
| 1037 | |||
| 1038 | return ret; | ||
| 1086 | } | 1039 | } |
| 1087 | 1040 | ||
| 1088 | /** Sets the size of a file on the phone. | 1041 | /** Sets the size of a file on the phone. |
| @@ -1096,37 +1049,38 @@ iphone_error_t afc_seek_file(afc_client_t client, uint64_t handle, int64_t offse | |||
| 1096 | * @note This function is more akin to ftruncate than truncate, and truncate | 1049 | * @note This function is more akin to ftruncate than truncate, and truncate |
| 1097 | * calls would have to open the file before calling this, sadly. | 1050 | * calls would have to open the file before calling this, sadly. |
| 1098 | */ | 1051 | */ |
| 1099 | iphone_error_t afc_truncate_file(afc_client_t client, uint64_t handle, uint64_t newsize) | 1052 | afc_error_t afc_file_truncate(afc_client_t client, uint64_t handle, uint64_t newsize) |
| 1100 | { | 1053 | { |
| 1101 | char *buffer = (char *) malloc(sizeof(char) * 16); | 1054 | char *buffer = (char *) malloc(sizeof(char) * 16); |
| 1102 | int bytes = 0; | 1055 | int bytes = 0; |
| 1056 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 1057 | |||
| 1058 | if (!client || (handle == 0)) | ||
| 1059 | return AFC_E_INVALID_ARGUMENT; | ||
| 1103 | 1060 | ||
| 1104 | afc_lock(client); | 1061 | afc_lock(client); |
| 1105 | 1062 | ||
| 1106 | // Send command | 1063 | // Send command |
| 1107 | memcpy(buffer, &handle, sizeof(uint64_t)); // handle | 1064 | memcpy(buffer, &handle, sizeof(uint64_t)); // handle |
| 1108 | memcpy(buffer + 8, &newsize, sizeof(uint64_t)); // newsize | 1065 | memcpy(buffer + 8, &newsize, sizeof(uint64_t)); // newsize |
| 1109 | client->afc_packet->operation = AFC_FILE_TRUNCATE; | 1066 | client->afc_packet->operation = AFC_OP_FILE_SET_SIZE; |
| 1110 | client->afc_packet->this_length = client->afc_packet->entire_length = 0; | 1067 | client->afc_packet->this_length = client->afc_packet->entire_length = 0; |
| 1111 | bytes = dispatch_AFC_packet(client, buffer, 16); | 1068 | bytes = afc_dispatch_packet(client, buffer, 16); |
| 1112 | free(buffer); | 1069 | free(buffer); |
| 1113 | buffer = NULL; | 1070 | buffer = NULL; |
| 1114 | 1071 | ||
| 1115 | if (bytes <= 0) { | 1072 | if (bytes <= 0) { |
| 1116 | afc_unlock(client); | 1073 | afc_unlock(client); |
| 1117 | return IPHONE_E_NOT_ENOUGH_DATA; | 1074 | return AFC_E_NOT_ENOUGH_DATA; |
| 1118 | } | 1075 | } |
| 1119 | // Receive response | 1076 | // Receive response |
| 1120 | bytes = receive_AFC_data(client, &buffer); | 1077 | ret = afc_receive_data(client, &buffer, &bytes); |
| 1121 | if (buffer) | 1078 | if (buffer) |
| 1122 | free(buffer); | 1079 | free(buffer); |
| 1123 | 1080 | ||
| 1124 | afc_unlock(client); | 1081 | afc_unlock(client); |
| 1125 | 1082 | ||
| 1126 | if (bytes < 0) { | 1083 | return ret; |
| 1127 | return IPHONE_E_AFC_ERROR; | ||
| 1128 | } | ||
| 1129 | return IPHONE_E_SUCCESS; | ||
| 1130 | } | 1084 | } |
| 1131 | 1085 | ||
| 1132 | /** Sets the size of a file on the phone without prior opening it. | 1086 | /** Sets the size of a file on the phone without prior opening it. |
| @@ -1135,18 +1089,19 @@ iphone_error_t afc_truncate_file(afc_client_t client, uint64_t handle, uint64_t | |||
| 1135 | * @param path The path of the file to be truncated. | 1089 | * @param path The path of the file to be truncated. |
| 1136 | * @param newsize The size to set the file to. | 1090 | * @param newsize The size to set the file to. |
| 1137 | * | 1091 | * |
| 1138 | * @return IPHONE_E_SUCCESS if everything went well, IPHONE_E_INVALID_ARG | 1092 | * @return AFC_E_SUCCESS if everything went well, AFC_E_INVALID_ARGUMENT |
| 1139 | * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise. | 1093 | * if arguments are NULL or invalid, AFC_E_NOT_ENOUGH_DATA otherwise. |
| 1140 | */ | 1094 | */ |
| 1141 | iphone_error_t afc_truncate(afc_client_t client, const char *path, off_t newsize) | 1095 | afc_error_t afc_truncate(afc_client_t client, const char *path, off_t newsize) |
| 1142 | { | 1096 | { |
| 1143 | char *response = NULL; | 1097 | char *response = NULL; |
| 1144 | char *send = (char *) malloc(sizeof(char) * (strlen(path) + 1 + 8)); | 1098 | char *send = (char *) malloc(sizeof(char) * (strlen(path) + 1 + 8)); |
| 1145 | int bytes = 0; | 1099 | int bytes = 0; |
| 1146 | uint64_t size_requested = newsize; | 1100 | uint64_t size_requested = newsize; |
| 1101 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 1147 | 1102 | ||
| 1148 | if (!client || !path || !client->afc_packet || client->sfd < 0) | 1103 | if (!client || !path || !client->afc_packet || client->sfd < 0) |
| 1149 | return IPHONE_E_INVALID_ARG; | 1104 | return AFC_E_INVALID_ARGUMENT; |
| 1150 | 1105 | ||
| 1151 | afc_lock(client); | 1106 | afc_lock(client); |
| 1152 | 1107 | ||
| @@ -1154,24 +1109,21 @@ iphone_error_t afc_truncate(afc_client_t client, const char *path, off_t newsize | |||
| 1154 | memcpy(send, &size_requested, 8); | 1109 | memcpy(send, &size_requested, 8); |
| 1155 | memcpy(send + 8, path, strlen(path) + 1); | 1110 | memcpy(send + 8, path, strlen(path) + 1); |
| 1156 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 1111 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 1157 | client->afc_packet->operation = AFC_TRUNCATE; | 1112 | client->afc_packet->operation = AFC_OP_TRUNCATE; |
| 1158 | bytes = dispatch_AFC_packet(client, send, 8 + strlen(path) + 1); | 1113 | bytes = afc_dispatch_packet(client, send, 8 + strlen(path) + 1); |
| 1159 | free(send); | 1114 | free(send); |
| 1160 | if (bytes <= 0) { | 1115 | if (bytes <= 0) { |
| 1161 | afc_unlock(client); | 1116 | afc_unlock(client); |
| 1162 | return IPHONE_E_NOT_ENOUGH_DATA; | 1117 | return AFC_E_NOT_ENOUGH_DATA; |
| 1163 | } | 1118 | } |
| 1164 | // Receive response | 1119 | // Receive response |
| 1165 | bytes = receive_AFC_data(client, &response); | 1120 | ret = afc_receive_data(client, &response, &bytes); |
| 1166 | if (response) | 1121 | if (response) |
| 1167 | free(response); | 1122 | free(response); |
| 1168 | 1123 | ||
| 1169 | afc_unlock(client); | 1124 | afc_unlock(client); |
| 1170 | 1125 | ||
| 1171 | if (bytes < 0) { | 1126 | return ret; |
| 1172 | return IPHONE_E_AFC_ERROR; | ||
| 1173 | } | ||
| 1174 | return IPHONE_E_SUCCESS; | ||
| 1175 | } | 1127 | } |
| 1176 | 1128 | ||
| 1177 | /** Creates a hard link or symbolic link on the device. | 1129 | /** Creates a hard link or symbolic link on the device. |
| @@ -1181,47 +1133,44 @@ iphone_error_t afc_truncate(afc_client_t client, const char *path, off_t newsize | |||
| 1181 | * @param target The file to be linked. | 1133 | * @param target The file to be linked. |
| 1182 | * @param linkname The name of link. | 1134 | * @param linkname The name of link. |
| 1183 | * | 1135 | * |
| 1184 | * @return IPHONE_E_SUCCESS if everything went well, IPHONE_E_INVALID_ARG | 1136 | * @return AFC_E_SUCCESS if everything went well, AFC_E_INVALID_ARGUMENT |
| 1185 | * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise. | 1137 | * if arguments are NULL or invalid, AFC_E_NOT_ENOUGH_DATA otherwise. |
| 1186 | */ | 1138 | */ |
| 1187 | iphone_error_t afc_make_link(afc_client_t client, afc_link_type_t linktype, const char *target, const char *linkname) | 1139 | afc_error_t afc_make_link(afc_client_t client, afc_link_type_t linktype, const char *target, const char *linkname) |
| 1188 | { | 1140 | { |
| 1189 | char *response = NULL; | 1141 | char *response = NULL; |
| 1190 | char *send = (char *) malloc(sizeof(char) * (strlen(target)+1 + strlen(linkname)+1 + 8)); | 1142 | char *send = (char *) malloc(sizeof(char) * (strlen(target)+1 + strlen(linkname)+1 + 8)); |
| 1191 | int bytes = 0; | 1143 | int bytes = 0; |
| 1192 | uint64_t type = linktype; | 1144 | uint64_t type = linktype; |
| 1145 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 1193 | 1146 | ||
| 1194 | if (!client || !target || !linkname || !client->afc_packet || client->sfd < 0) | 1147 | if (!client || !target || !linkname || !client->afc_packet || client->sfd < 0) |
| 1195 | return IPHONE_E_INVALID_ARG; | 1148 | return AFC_E_INVALID_ARGUMENT; |
| 1196 | 1149 | ||
| 1197 | afc_lock(client); | 1150 | afc_lock(client); |
| 1198 | 1151 | ||
| 1199 | log_debug_msg("link type: %lld\n", type); | 1152 | log_debug_msg("%s: link type: %lld\n", __func__, type); |
| 1200 | log_debug_msg("target: %s, length:%d\n", target, strlen(target)); | 1153 | log_debug_msg("%s: target: %s, length:%d\n", __func__, target, strlen(target)); |
| 1201 | log_debug_msg("linkname: %s, length:%d\n", linkname, strlen(linkname)); | 1154 | log_debug_msg("%s: linkname: %s, length:%d\n", __func__, linkname, strlen(linkname)); |
| 1202 | 1155 | ||
| 1203 | // Send command | 1156 | // Send command |
| 1204 | memcpy(send, &type, 8); | 1157 | memcpy(send, &type, 8); |
| 1205 | memcpy(send + 8, target, strlen(target) + 1); | 1158 | memcpy(send + 8, target, strlen(target) + 1); |
| 1206 | memcpy(send + 8 + strlen(target) + 1, linkname, strlen(linkname) + 1); | 1159 | memcpy(send + 8 + strlen(target) + 1, linkname, strlen(linkname) + 1); |
| 1207 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 1160 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 1208 | client->afc_packet->operation = AFC_MAKE_LINK; | 1161 | client->afc_packet->operation = AFC_OP_MAKE_LINK; |
| 1209 | bytes = dispatch_AFC_packet(client, send, 8 + strlen(linkname) + 1 + strlen(target) + 1); | 1162 | bytes = afc_dispatch_packet(client, send, 8 + strlen(linkname) + 1 + strlen(target) + 1); |
| 1210 | free(send); | 1163 | free(send); |
| 1211 | if (bytes <= 0) { | 1164 | if (bytes <= 0) { |
| 1212 | afc_unlock(client); | 1165 | afc_unlock(client); |
| 1213 | return IPHONE_E_NOT_ENOUGH_DATA; | 1166 | return AFC_E_NOT_ENOUGH_DATA; |
| 1214 | } | 1167 | } |
| 1215 | // Receive response | 1168 | // Receive response |
| 1216 | bytes = receive_AFC_data(client, &response); | 1169 | ret = afc_receive_data(client, &response, &bytes); |
| 1217 | if (response) | 1170 | if (response) |
| 1218 | free(response); | 1171 | free(response); |
| 1219 | 1172 | ||
| 1220 | afc_unlock(client); | 1173 | afc_unlock(client); |
| 1221 | 1174 | ||
| 1222 | if (bytes < 0) { | 1175 | return ret; |
| 1223 | return IPHONE_E_NOT_ENOUGH_DATA; | ||
| 1224 | } else { | ||
| 1225 | return IPHONE_E_SUCCESS; | ||
| 1226 | } | ||
| 1227 | } | 1176 | } |
