mirror of
https://github.com/libimobiledevice/libplist
synced 2026-06-08 15:29:34 +00:00
make all functions return an error code.
This commit is contained in:
@@ -46,6 +46,8 @@ extern "C" {
|
||||
//afc specific error
|
||||
#define IPHONE_E_NO_SUCH_FILE -10
|
||||
|
||||
typedef short iphone_error_t;
|
||||
|
||||
enum {
|
||||
AFC_FILE_READ = 0x00000002, // seems to be able to read and write files
|
||||
AFC_FILE_WRITE = 0x00000003, // writes and creates a file, blanks it out, etc.
|
||||
@@ -73,44 +75,44 @@ struct iphone_afc_file_int;
|
||||
typedef struct iphone_afc_file_int *iphone_afc_file_t;
|
||||
|
||||
//device related functions
|
||||
int iphone_get_device ( iphone_device_t *device );
|
||||
void iphone_free_device ( iphone_device_t device );
|
||||
iphone_error_t iphone_get_device ( iphone_device_t *device );
|
||||
iphone_error_t iphone_free_device ( iphone_device_t device );
|
||||
|
||||
|
||||
//lockdownd related functions
|
||||
int iphone_lckd_new_client ( iphone_device_t device, iphone_lckd_client_t *client );
|
||||
void iphone_lckd_free_client( iphone_lckd_client_t client );
|
||||
iphone_error_t iphone_lckd_new_client ( iphone_device_t device, iphone_lckd_client_t *client );
|
||||
iphone_error_t iphone_lckd_free_client( iphone_lckd_client_t client );
|
||||
|
||||
int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service );
|
||||
int iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data );
|
||||
int iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t length );
|
||||
iphone_error_t iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service, int *port );
|
||||
iphone_error_t iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data, uint32_t *recv_bytes );
|
||||
iphone_error_t iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t length, uint32_t *recv_bytes );
|
||||
|
||||
|
||||
//usbmux related functions
|
||||
int iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t dst_port, iphone_umux_client_t *client );
|
||||
void iphone_mux_free_client ( iphone_umux_client_t client );
|
||||
iphone_error_t iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t dst_port, iphone_umux_client_t *client );
|
||||
iphone_error_t iphone_mux_free_client ( iphone_umux_client_t client );
|
||||
|
||||
int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen );
|
||||
int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen );
|
||||
iphone_error_t iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen, uint32_t *sent_bytes );
|
||||
iphone_error_t iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen, uint32_t *recv_bytes );
|
||||
|
||||
|
||||
//afc related functions
|
||||
int iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_afc_client_t *client );
|
||||
void iphone_afc_free_client ( iphone_afc_client_t client );
|
||||
iphone_error_t iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_afc_client_t *client );
|
||||
iphone_error_t iphone_afc_free_client ( iphone_afc_client_t client );
|
||||
|
||||
char **iphone_afc_get_devinfo ( iphone_afc_client_t client );
|
||||
char **iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir);
|
||||
iphone_error_t iphone_afc_get_devinfo ( iphone_afc_client_t client, char ***infos );
|
||||
iphone_error_t iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir, char ***list);
|
||||
|
||||
int iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename, struct stat *stbuf );
|
||||
int iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uint32_t file_mode, iphone_afc_file_t *file );
|
||||
void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file);
|
||||
int iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, char *data, int length);
|
||||
int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, const char *data, int length);
|
||||
int iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, int seekpos);
|
||||
int iphone_afc_truncate_file ( iphone_afc_client_t client, iphone_afc_file_t file, uint32_t newsize);
|
||||
int iphone_afc_delete_file ( iphone_afc_client_t client, const char *path);
|
||||
int iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const char *to);
|
||||
int iphone_afc_mkdir ( iphone_afc_client_t client, const char *dir);
|
||||
iphone_error_t iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename, struct stat *stbuf );
|
||||
iphone_error_t iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uint32_t file_mode, iphone_afc_file_t *file );
|
||||
iphone_error_t iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file);
|
||||
iphone_error_t iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, char *data, int length, uint32_t *bytes);
|
||||
iphone_error_t iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, const char *data, int length, uint32_t *bytes);
|
||||
iphone_error_t iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, int seekpos);
|
||||
iphone_error_t iphone_afc_truncate_file ( iphone_afc_client_t client, iphone_afc_file_t file, uint32_t newsize);
|
||||
iphone_error_t iphone_afc_delete_file ( iphone_afc_client_t client, const char *path);
|
||||
iphone_error_t iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const char *to);
|
||||
iphone_error_t iphone_afc_mkdir ( iphone_afc_client_t client, const char *dir);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -58,7 +58,7 @@ static void afc_unlock(iphone_afc_client_t client) { // just to be pretty
|
||||
*
|
||||
* @return A handle to the newly-connected client or NULL upon error.
|
||||
*/
|
||||
int iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_afc_client_t *client ) {
|
||||
iphone_error_t iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_afc_client_t *client ) {
|
||||
int ret = IPHONE_E_SUCCESS;
|
||||
iphone_afc_client_t client_loc = (iphone_afc_client_t)malloc(sizeof(struct iphone_afc_client_int));
|
||||
|
||||
@@ -100,12 +100,14 @@ int iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port,
|
||||
*
|
||||
* @param client The client to disconnect.
|
||||
*/
|
||||
void iphone_afc_free_client ( iphone_afc_client_t client ) {
|
||||
if (!client || !client->connection || !client->afc_packet) return;
|
||||
iphone_error_t iphone_afc_free_client ( iphone_afc_client_t client ) {
|
||||
if (!client || !client->connection || !client->afc_packet)
|
||||
return IPHONE_E_INVALID_ARG;
|
||||
|
||||
iphone_mux_free_client(client->connection);
|
||||
free(client->afc_packet);
|
||||
free(client);
|
||||
return IPHONE_E_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -324,11 +326,12 @@ static char **make_strings_list(char *tokens, int true_length) {
|
||||
* @return A char ** list of files in that directory, terminated by an empty
|
||||
* string for now or NULL if there was an error.
|
||||
*/
|
||||
char **iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir) {
|
||||
iphone_error_t iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir, char ***list) {
|
||||
int bytes = 0;
|
||||
char *data = NULL, **list = NULL;
|
||||
char *data = NULL, **list_loc = NULL;
|
||||
iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
|
||||
|
||||
if (!client || !dir) return NULL;
|
||||
if (!client || !dir || !list) return IPHONE_E_INVALID_ARG;
|
||||
|
||||
afc_lock(client);
|
||||
|
||||
@@ -339,23 +342,25 @@ char **iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir) {
|
||||
bytes = dispatch_AFC_packet(client, dir, strlen(dir));
|
||||
if (bytes <= 0) {
|
||||
afc_unlock(client);
|
||||
return NULL;
|
||||
return IPHONE_E_NOT_ENOUGH_DATA;
|
||||
}
|
||||
|
||||
// Receive the data
|
||||
bytes = receive_AFC_data(client, &data);
|
||||
if (bytes < 0 && !data) {
|
||||
afc_unlock(client);
|
||||
return NULL;
|
||||
return IPHONE_E_NOT_ENOUGH_DATA;
|
||||
}
|
||||
|
||||
// Parse the data
|
||||
list = make_strings_list(data, bytes);
|
||||
list_loc = make_strings_list(data, bytes);
|
||||
if (list_loc) ret = IPHONE_E_SUCCESS;
|
||||
if (data) free(data);
|
||||
|
||||
afc_unlock(client);
|
||||
*list = list_loc;
|
||||
|
||||
return list;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Get device info for a client connection to phone. (free space on disk, etc.)
|
||||
@@ -365,11 +370,11 @@ char **iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir) {
|
||||
* @return A char ** list of parameters as given by AFC or NULL if there was an
|
||||
* error.
|
||||
*/
|
||||
char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) {
|
||||
iphone_error_t iphone_afc_get_devinfo ( iphone_afc_client_t client, char ***infos) {
|
||||
int bytes = 0;
|
||||
char *data = NULL, **list = NULL;
|
||||
|
||||
if (!client) return NULL;
|
||||
if (!client || !infos) return IPHONE_E_INVALID_ARG;
|
||||
|
||||
afc_lock(client);
|
||||
|
||||
@@ -379,14 +384,14 @@ char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) {
|
||||
bytes = dispatch_AFC_packet(client, NULL, 0);
|
||||
if (bytes < 0) {
|
||||
afc_unlock(client);
|
||||
return NULL;
|
||||
return IPHONE_E_NOT_ENOUGH_DATA;
|
||||
}
|
||||
|
||||
// Receive the data
|
||||
bytes = receive_AFC_data(client, &data);
|
||||
if (bytes < 0 && !data) {
|
||||
afc_unlock(client);
|
||||
return NULL;
|
||||
return IPHONE_E_NOT_ENOUGH_DATA;
|
||||
}
|
||||
|
||||
// Parse the data
|
||||
@@ -394,8 +399,8 @@ char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) {
|
||||
if (data) free(data);
|
||||
|
||||
afc_unlock(client);
|
||||
|
||||
return list;
|
||||
*infos = list;
|
||||
return IPHONE_E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Deletes a file.
|
||||
@@ -406,7 +411,7 @@ char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) {
|
||||
* @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG
|
||||
* if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise.
|
||||
*/
|
||||
int iphone_afc_delete_file ( iphone_afc_client_t client, const char *path) {
|
||||
iphone_error_t iphone_afc_delete_file ( iphone_afc_client_t client, const char *path) {
|
||||
char *response = NULL;
|
||||
int bytes;
|
||||
|
||||
@@ -445,7 +450,7 @@ int iphone_afc_delete_file ( iphone_afc_client_t client, const char *path) {
|
||||
* @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG
|
||||
* if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise.
|
||||
*/
|
||||
int iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const char *to) {
|
||||
iphone_error_t iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const char *to) {
|
||||
char *response = NULL;
|
||||
char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32)));
|
||||
int bytes = 0;
|
||||
@@ -488,7 +493,7 @@ int iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const
|
||||
* @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG
|
||||
* if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise.
|
||||
*/
|
||||
int iphone_afc_mkdir ( iphone_afc_client_t client, const char *dir) {
|
||||
iphone_error_t iphone_afc_mkdir ( iphone_afc_client_t client, const char *dir) {
|
||||
int bytes = 0;
|
||||
char *response = NULL;
|
||||
|
||||
@@ -586,7 +591,7 @@ iphone_afc_file_t afc_get_file_info(iphone_afc_client_t client, const char *path
|
||||
* @return A pointer to an AFCFile struct containing the information received,
|
||||
* or NULL on failure.
|
||||
*/
|
||||
int iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename, struct stat *stbuf ) {
|
||||
iphone_error_t iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename, struct stat *stbuf ) {
|
||||
|
||||
int ret = IPHONE_E_SUCCESS;
|
||||
if (!client ||!client->connection || !client->afc_packet || !stbuf) return IPHONE_E_INVALID_ARG;
|
||||
@@ -620,7 +625,7 @@ int iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename,
|
||||
* received by afc_get_file_info) as well as the handle to the file or
|
||||
* NULL in the case of failure.
|
||||
*/
|
||||
int iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uint32_t file_mode, iphone_afc_file_t *file ) {
|
||||
iphone_error_t iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uint32_t file_mode, iphone_afc_file_t *file ) {
|
||||
iphone_afc_file_t file_loc = NULL;
|
||||
uint32 ag = 0;
|
||||
int bytes = 0, length = 0;
|
||||
@@ -677,12 +682,12 @@ int iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uin
|
||||
*
|
||||
* @return The number of bytes read if successful. If there was an error -1.
|
||||
*/
|
||||
int iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, char *data, int length) {
|
||||
iphone_error_t iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, char *data, int length, uint32_t *bytes) {
|
||||
char *input = NULL;
|
||||
int current_count = 0, bytes = 0;
|
||||
int current_count = 0, bytes_loc = 0;
|
||||
const int MAXIMUM_READ_SIZE = 1 << 16;
|
||||
|
||||
if (!client || !client->afc_packet || !client->connection || !file) return -1;
|
||||
if (!client || !client->afc_packet || !client->connection || !file) return IPHONE_E_INVALID_ARG;
|
||||
if (debug) fprintf(stderr, "afc_read_file called for length %i\n", length);
|
||||
|
||||
afc_lock(client);
|
||||
@@ -698,40 +703,41 @@ int iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, c
|
||||
packet->size = ((length - current_count) < MAXIMUM_READ_SIZE) ? (length - current_count) : MAXIMUM_READ_SIZE;
|
||||
client->afc_packet->operation = AFC_READ;
|
||||
client->afc_packet->entire_length = client->afc_packet->this_length = 0;
|
||||
bytes = dispatch_AFC_packet(client, (char*)packet, sizeof(AFCFilePacket));
|
||||
bytes_loc = dispatch_AFC_packet(client, (char*)packet, sizeof(AFCFilePacket));
|
||||
free(packet);
|
||||
|
||||
if (bytes <= 0) {
|
||||
if (bytes_loc <= 0) {
|
||||
afc_unlock(client);
|
||||
return -1;
|
||||
return IPHONE_E_NOT_ENOUGH_DATA;
|
||||
}
|
||||
|
||||
// Receive the data
|
||||
bytes = receive_AFC_data(client, &input);
|
||||
if (debug) fprintf(stderr, "afc_read_file: bytes returned: %i\n", bytes);
|
||||
bytes_loc = receive_AFC_data(client, &input);
|
||||
if (debug) fprintf(stderr, "afc_read_file: bytes returned: %i\n", bytes_loc);
|
||||
if (bytes < 0) {
|
||||
if (input) free(input);
|
||||
afc_unlock(client);
|
||||
return -1;
|
||||
return IPHONE_E_NOT_ENOUGH_DATA;
|
||||
} else if (bytes == 0) {
|
||||
if (input) free(input);
|
||||
afc_unlock(client);
|
||||
return current_count;
|
||||
*bytes = current_count;
|
||||
return IPHONE_E_SUCCESS; //FIXME check that's actually a success
|
||||
} else {
|
||||
if (input) {
|
||||
if (debug) fprintf(stderr, "afc_read_file: %d\n", bytes);
|
||||
memcpy(data+current_count, input, (bytes > length) ? length : bytes);
|
||||
if (debug) fprintf(stderr, "afc_read_file: %d\n", bytes_loc);
|
||||
memcpy(data+current_count, input, (bytes_loc > length) ? length : bytes_loc);
|
||||
free(input);
|
||||
input = NULL;
|
||||
current_count += (bytes > length) ? length : bytes;
|
||||
current_count += (bytes_loc > length) ? length : bytes_loc;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (debug) fprintf(stderr, "afc_read_file: returning current_count as %i\n", current_count);
|
||||
|
||||
afc_unlock(client);
|
||||
|
||||
return current_count;
|
||||
*bytes = current_count;
|
||||
return IPHONE_E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Writes a given number of bytes to a file.
|
||||
@@ -744,13 +750,13 @@ int iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, c
|
||||
* @return The number of bytes written to the file, or a value less than 0 if
|
||||
* none were written...
|
||||
*/
|
||||
int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, const char *data, int length) {
|
||||
iphone_error_t iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, const char *data, int length, uint32_t *bytes) {
|
||||
char *acknowledgement = NULL;
|
||||
const int MAXIMUM_WRITE_SIZE = 1 << 16;
|
||||
uint32 zero = 0, bytes = 0, segments = (length / MAXIMUM_WRITE_SIZE), current_count = 0, i = 0;
|
||||
uint32 zero = 0, bytes_loc = 0, segments = (length / MAXIMUM_WRITE_SIZE), current_count = 0, i = 0;
|
||||
char *out_buffer = NULL;
|
||||
|
||||
if (!client ||!client->afc_packet || !client->connection || !file) return -1;
|
||||
if (!client ||!client->afc_packet || !client->connection || !file || !bytes_loc) return IPHONE_E_INVALID_ARG;
|
||||
|
||||
afc_lock(client);
|
||||
|
||||
@@ -766,19 +772,19 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file,
|
||||
memcpy(out_buffer, (char*)&file->filehandle, sizeof(uint32));
|
||||
memcpy(out_buffer+4, (char*)&zero, sizeof(uint32));
|
||||
memcpy(out_buffer+8, data+current_count, MAXIMUM_WRITE_SIZE);
|
||||
bytes = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8);
|
||||
if (bytes < 0) {
|
||||
bytes_loc = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8);
|
||||
if (bytes_loc < 0) {
|
||||
afc_unlock(client);
|
||||
return bytes;
|
||||
return IPHONE_E_NOT_ENOUGH_DATA;
|
||||
}
|
||||
free(out_buffer);
|
||||
out_buffer = NULL;
|
||||
|
||||
current_count += bytes;
|
||||
bytes = receive_AFC_data(client, &acknowledgement);
|
||||
if (bytes < 0) {
|
||||
current_count += bytes_loc;
|
||||
bytes_loc = receive_AFC_data(client, &acknowledgement);
|
||||
if (bytes_loc < 0) {
|
||||
afc_unlock(client);
|
||||
return current_count;
|
||||
return IPHONE_E_NOT_ENOUGH_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -786,7 +792,8 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file,
|
||||
// this length is fine because it's always sizeof(AFCPacket) + 8, but to be sure we do it again
|
||||
if (current_count == length) {
|
||||
afc_unlock(client);
|
||||
return current_count;
|
||||
*bytes = current_count;
|
||||
return IPHONE_E_SUCCESS;
|
||||
}
|
||||
|
||||
client->afc_packet->this_length = sizeof(AFCPacket) + 8;
|
||||
@@ -796,25 +803,26 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file,
|
||||
memcpy(out_buffer, (char*)&file->filehandle, sizeof(uint32));
|
||||
memcpy(out_buffer+4, (char*)&zero, sizeof(uint32));
|
||||
memcpy(out_buffer+8, data+current_count, (length - current_count));
|
||||
bytes = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8);
|
||||
bytes_loc = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8);
|
||||
free(out_buffer);
|
||||
out_buffer = NULL;
|
||||
|
||||
current_count += bytes;
|
||||
current_count += bytes_loc;
|
||||
|
||||
if (bytes <= 0) {
|
||||
if (bytes_loc <= 0) {
|
||||
afc_unlock(client);
|
||||
return current_count;
|
||||
*bytes = current_count;
|
||||
return IPHONE_E_SUCCESS;
|
||||
}
|
||||
|
||||
zero = bytes;
|
||||
bytes = receive_AFC_data(client, &acknowledgement);
|
||||
zero = bytes_loc;
|
||||
bytes_loc = receive_AFC_data(client, &acknowledgement);
|
||||
afc_unlock(client);
|
||||
if (bytes < 0) {
|
||||
if (bytes_loc < 0) {
|
||||
if (debug) fprintf(stderr, "afc_write_file: uh oh?\n");
|
||||
}
|
||||
|
||||
return current_count;
|
||||
|
||||
return IPHONE_E_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
/** Closes a file on the phone.
|
||||
@@ -823,7 +831,8 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file,
|
||||
* @param file A pointer to an AFCFile struct containing the file handle of the
|
||||
* file to close.
|
||||
*/
|
||||
void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file) {
|
||||
iphone_error_t iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file) {
|
||||
if (!client || !file) return IPHONE_E_INVALID_ARG;
|
||||
char *buffer = malloc(sizeof(char) * 8);
|
||||
uint32 zero = 0;
|
||||
int bytes = 0;
|
||||
@@ -846,7 +855,7 @@ void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file)
|
||||
|
||||
if (bytes <= 0) {
|
||||
afc_unlock(client);
|
||||
return;
|
||||
return IPHONE_E_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
// Receive the response
|
||||
@@ -854,6 +863,7 @@ void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file)
|
||||
if (buffer) free(buffer);
|
||||
free(file);
|
||||
afc_unlock(client);
|
||||
return IPHONE_E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Seeks to a given position of a pre-opened file on the phone.
|
||||
@@ -865,7 +875,7 @@ void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file)
|
||||
*
|
||||
* @return IPHONE_E_SUCCESS on success, IPHONE_E_NOT_ENOUGH_DATA on failure.
|
||||
*/
|
||||
int iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, int seekpos) {
|
||||
iphone_error_t iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, int seekpos) {
|
||||
char *buffer = (char*)malloc(sizeof(char) * 24);
|
||||
uint32 seekto = 0, bytes = 0, zero = 0;
|
||||
|
||||
@@ -916,7 +926,7 @@ int iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, i
|
||||
* @note This function is more akin to ftruncate than truncate, and truncate
|
||||
* calls would have to open the file before calling this, sadly.
|
||||
*/
|
||||
int iphone_afc_truncate_file ( iphone_afc_client_t client, iphone_afc_file_t file, uint32_t newsize) {
|
||||
iphone_error_t iphone_afc_truncate_file ( iphone_afc_client_t client, iphone_afc_file_t file, uint32_t newsize) {
|
||||
char *buffer = (char*)malloc(sizeof(char) * 16);
|
||||
uint32 bytes = 0, zero = 0;
|
||||
|
||||
|
||||
+16
-9
@@ -34,7 +34,7 @@ extern int debug;
|
||||
* @return A structure with data on the first iPhone it finds. (Or NULL, on
|
||||
* error)
|
||||
*/
|
||||
int iphone_get_device ( iphone_device_t *device ){
|
||||
iphone_error_t iphone_get_device ( iphone_device_t *device ){
|
||||
//check we can actually write in device
|
||||
if (!device || (device && *device))
|
||||
return IPHONE_E_INVALID_ARG;
|
||||
@@ -102,7 +102,7 @@ int iphone_get_device ( iphone_device_t *device ){
|
||||
iphone_free_device(phone);
|
||||
if (debug) fprintf(stderr, "get_iPhone(): Invalid version message -- header too short.\n");
|
||||
if (debug && bytes < 0) fprintf(stderr, "get_iPhone(): libusb error message %d: %s (%s)\n",
|
||||
bytes, usb_strerror(), strerror(-bytes));
|
||||
bytes, usb_strerror(), strerror(-bytes));
|
||||
return IPHONE_E_NOT_ENOUGH_DATA;
|
||||
}
|
||||
|
||||
@@ -134,14 +134,21 @@ int iphone_get_device ( iphone_device_t *device ){
|
||||
*
|
||||
* @param phone A pointer to an iPhone structure.
|
||||
*/
|
||||
void iphone_free_device ( iphone_device_t device ) {
|
||||
if (device->buffer) free(device->buffer);
|
||||
if (device->device) {
|
||||
usb_release_interface(device->device, 1);
|
||||
usb_reset(device->device);
|
||||
usb_close(device->device);
|
||||
iphone_error_t iphone_free_device ( iphone_device_t device ) {
|
||||
if (!device) return IPHONE_E_INVALID_ARG;
|
||||
iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
|
||||
|
||||
if (device->buffer) {
|
||||
free(device->buffer);
|
||||
if (device->device) {
|
||||
usb_release_interface(device->device, 1);
|
||||
usb_reset(device->device);
|
||||
usb_close(device->device);
|
||||
ret = IPHONE_E_SUCCESS;
|
||||
}
|
||||
free(device);
|
||||
}
|
||||
free(device);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Sends data to the phone
|
||||
|
||||
+52
-32
@@ -94,15 +94,18 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone) {
|
||||
*
|
||||
* @param control The lockdown client
|
||||
*/
|
||||
void iphone_lckd_free_client( iphone_lckd_client_t client ) {
|
||||
if (!client) return;
|
||||
iphone_error_t iphone_lckd_free_client( iphone_lckd_client_t client ) {
|
||||
if (!client) return IPHONE_E_INVALID_ARG;
|
||||
iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
|
||||
|
||||
if (client->connection) {
|
||||
iphone_mux_free_client(client->connection);
|
||||
ret = iphone_mux_free_client(client->connection);
|
||||
}
|
||||
|
||||
if (client->ssl_session) gnutls_deinit(*client->ssl_session);
|
||||
free(client->ssl_session);
|
||||
free(client);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Polls the iPhone for lockdownd data.
|
||||
@@ -113,20 +116,28 @@ void iphone_lckd_free_client( iphone_lckd_client_t client ) {
|
||||
*
|
||||
* @return The number of bytes received
|
||||
*/
|
||||
int iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data ) {
|
||||
if (!client) return 0;
|
||||
iphone_error_t iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data, uint32_t *recv_bytes ) {
|
||||
if (!client || dump_data || !recv_bytes) return IPHONE_E_INVALID_ARG;
|
||||
iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
|
||||
char *receive;
|
||||
uint32 datalen = 0, bytes = 0;
|
||||
|
||||
if (!client->in_SSL) bytes = iphone_mux_recv(client->connection, (char *)&datalen, sizeof(datalen));
|
||||
else bytes = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen));
|
||||
if (!client->in_SSL) ret = iphone_mux_recv(client->connection, (char *)&datalen, sizeof(datalen), &bytes);
|
||||
else {
|
||||
bytes = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen));
|
||||
if (bytes > 0) ret = IPHONE_E_SUCCESS;
|
||||
}
|
||||
datalen = ntohl(datalen);
|
||||
|
||||
receive = (char*)malloc(sizeof(char) * datalen);
|
||||
if (!client->in_SSL) bytes = iphone_mux_recv(client->connection, receive, datalen);
|
||||
else bytes = gnutls_record_recv(*client->ssl_session, receive, datalen);
|
||||
if (!client->in_SSL) ret = iphone_mux_recv(client->connection, receive, datalen, &bytes);
|
||||
else {
|
||||
bytes = gnutls_record_recv(*client->ssl_session, receive, datalen);
|
||||
if (bytes > 0) ret = IPHONE_E_SUCCESS;
|
||||
}
|
||||
*dump_data = receive;
|
||||
return bytes;
|
||||
*recv_bytes = bytes;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Sends lockdownd data to the iPhone
|
||||
@@ -140,11 +151,12 @@ int iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data ) {
|
||||
*
|
||||
* @return The number of bytes sent
|
||||
*/
|
||||
int iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t length ) {
|
||||
if (!client) return 0;
|
||||
iphone_error_t iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t length, uint32_t *sent_bytes ) {
|
||||
if (!client || !raw_data || length == 0 || !sent_bytes) return IPHONE_E_INVALID_ARG;
|
||||
char *real_query;
|
||||
int bytes;
|
||||
|
||||
iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
|
||||
|
||||
real_query = (char*)malloc(sizeof(char) * (length+4));
|
||||
length = htonl(length);
|
||||
memcpy(real_query, &length, sizeof(length));
|
||||
@@ -157,11 +169,15 @@ int iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t len
|
||||
packet = NULL;
|
||||
}
|
||||
|
||||
if (!client->in_SSL) bytes = iphone_mux_send(client->connection, real_query, ntohl(length)+sizeof(length));
|
||||
else gnutls_record_send(*client->ssl_session, real_query, ntohl(length)+sizeof(length));
|
||||
if (!client->in_SSL) ret = iphone_mux_send(client->connection, real_query, ntohl(length)+sizeof(length), &bytes);
|
||||
else {
|
||||
gnutls_record_send(*client->ssl_session, real_query, ntohl(length)+sizeof(length));
|
||||
ret = IPHONE_E_SUCCESS;
|
||||
}
|
||||
if (debug) printf("lockdownd_send(): sent it!\n");
|
||||
free(real_query);
|
||||
return bytes;
|
||||
*sent_bytes = bytes;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Initiates the handshake for the lockdown session. Part of the lockdownd handshake.
|
||||
@@ -307,11 +323,11 @@ int lockdownd_get_device_public_key(iphone_lckd_client_t control, char **public_
|
||||
*
|
||||
* @return 1 on success and 0 on failure
|
||||
*/
|
||||
int iphone_lckd_new_client ( iphone_device_t device, iphone_lckd_client_t *client )
|
||||
iphone_error_t iphone_lckd_new_client ( iphone_device_t device, iphone_lckd_client_t *client )
|
||||
{
|
||||
if (!device || !client || (client && *client) )
|
||||
return IPHONE_E_INVALID_ARG;
|
||||
int ret = IPHONE_E_SUCCESS;
|
||||
iphone_error_t ret = IPHONE_E_SUCCESS;
|
||||
char *host_id = NULL;
|
||||
|
||||
iphone_lckd_client_t client_loc = new_lockdownd_client( device );
|
||||
@@ -815,14 +831,15 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_
|
||||
*
|
||||
* @return The port number the service was started on or 0 on failure.
|
||||
*/
|
||||
int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service ) {
|
||||
if (!client) return 0;
|
||||
iphone_error_t iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service, int *port ) {
|
||||
if (!client || !service || !port) return IPHONE_E_INVALID_ARG;
|
||||
|
||||
char* host_id = get_host_id();
|
||||
if (host_id && !client->in_SSL && !lockdownd_start_SSL_session(client, host_id)) return 0;
|
||||
if (!host_id) return IPHONE_E_INVALID_CONF;
|
||||
if (!client->in_SSL && !lockdownd_start_SSL_session(client, host_id)) return IPHONE_E_SSL_ERROR;
|
||||
|
||||
char *XML_query, **dictionary;
|
||||
uint32 length, i = 0, port = 0;
|
||||
uint32 length, i = 0, port_loc = 0;
|
||||
uint8 result = 0;
|
||||
|
||||
free(host_id);
|
||||
@@ -832,9 +849,9 @@ int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service
|
||||
xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0);
|
||||
xmlNode *key;
|
||||
key = add_key_str_dict_element(plist, dict, "Request", "StartService", 1);
|
||||
if (!key) { xmlFreeDoc(plist); return 0; }
|
||||
if (!key) { xmlFreeDoc(plist); return IPHONE_E_UNKNOWN_ERROR; }
|
||||
key = add_key_str_dict_element(plist, dict, "Service", service, 1);
|
||||
if (!key) { xmlFreeDoc(plist); return 0; }
|
||||
if (!key) { xmlFreeDoc(plist); return IPHONE_E_UNKNOWN_ERROR; }
|
||||
|
||||
xmlDocDumpMemory(plist, (xmlChar **)&XML_query, &length);
|
||||
|
||||
@@ -845,24 +862,24 @@ int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service
|
||||
|
||||
xmlFreeDoc(plist);
|
||||
|
||||
if (length <= 0) return 0;
|
||||
if (length <= 0) return IPHONE_E_NOT_ENOUGH_DATA;
|
||||
else {
|
||||
plist = xmlReadMemory(XML_query, length, NULL, NULL, 0);
|
||||
if (!plist) return 0;
|
||||
if (!plist) return IPHONE_E_UNKNOWN_ERROR;
|
||||
dict = xmlDocGetRootElement(plist);
|
||||
if (!dict) return 0;
|
||||
if (!dict) return IPHONE_E_UNKNOWN_ERROR;
|
||||
for (dict = dict->children; dict; dict = dict->next) {
|
||||
if (!xmlStrcmp(dict->name, "dict")) break;
|
||||
}
|
||||
|
||||
if (!dict) return 0;
|
||||
if (!dict) return IPHONE_E_UNKNOWN_ERROR;
|
||||
dictionary = read_dict_element_strings(dict);
|
||||
|
||||
for (i = 0; dictionary[i]; i+=2) {
|
||||
if (debug) printf("lockdownd_start_service() dictionary %s: %s\n", dictionary[i], dictionary[i+1]);
|
||||
|
||||
if (!xmlStrcmp(dictionary[i], "Port")) {
|
||||
port = atoi(dictionary[i+1]);
|
||||
port_loc = atoi(dictionary[i+1]);
|
||||
if (debug) printf("lockdownd_start_service() atoi'd port: %i\n", port);
|
||||
}
|
||||
|
||||
@@ -882,9 +899,12 @@ int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service
|
||||
free(XML_query);
|
||||
xmlFreeDoc(plist);
|
||||
free_dictionary(dictionary);
|
||||
if (port && result) return port;
|
||||
else return 0;
|
||||
if (port && result) {
|
||||
*port = port_loc;
|
||||
return IPHONE_E_SUCCESS;
|
||||
}
|
||||
else return IPHONE_E_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return IPHONE_E_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
+30
-18
@@ -116,7 +116,7 @@ void add_connection(iphone_umux_client_t connection) {
|
||||
* @param client A mux TCP header for the connection which is used for tracking and data transfer.
|
||||
* @return IPHONE_E_SUCCESS on success, an error code otherwise.
|
||||
*/
|
||||
int iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t dst_port, iphone_umux_client_t *client ){
|
||||
iphone_error_t iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t dst_port, iphone_umux_client_t *client ){
|
||||
if (!device || !src_port || !dst_port)
|
||||
return IPHONE_E_INVALID_ARG;
|
||||
|
||||
@@ -165,8 +165,10 @@ int iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t
|
||||
* @note Once a connection is closed it may not be used again.
|
||||
*
|
||||
* @param connection The connection to close.
|
||||
*
|
||||
* @return IPHONE_E_SUCCESS on success.
|
||||
*/
|
||||
void iphone_mux_free_client ( iphone_umux_client_t client ) {
|
||||
iphone_error_t iphone_mux_free_client ( iphone_umux_client_t client ) {
|
||||
if (!client || !client->phone) return;
|
||||
|
||||
client->header->tcp_flags = 0x04;
|
||||
@@ -183,6 +185,8 @@ void iphone_mux_free_client ( iphone_umux_client_t client ) {
|
||||
printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror());
|
||||
|
||||
delete_connection(client);
|
||||
|
||||
return IPHONE_E_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -192,15 +196,16 @@ void iphone_mux_free_client ( iphone_umux_client_t client ) {
|
||||
* @param client The client we're sending data on.
|
||||
* @param data A pointer to the data to send.
|
||||
* @param datalen How much data we're sending.
|
||||
* @param sent_bytes The number of bytes sent, minus the header (28)
|
||||
*
|
||||
* @return The number of bytes sent, minus the header (28), or -1 on error.
|
||||
* @return IPHONE_E_SUCCESS on success.
|
||||
*/
|
||||
|
||||
int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen ) {
|
||||
if (!client->phone || !client || !data || datalen == 0) return -1;
|
||||
iphone_error_t iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen, uint32_t *sent_bytes ) {
|
||||
if (!client->phone || !client || !data || datalen == 0 || !sent_bytes) return IPHONE_E_INVALID_ARG;
|
||||
// client->scnt and client->ocnt should already be in host notation...
|
||||
// we don't need to change them juuuust yet.
|
||||
int bytes = 0;
|
||||
*sent_bytes = 0;
|
||||
if (debug) printf("mux_send(): client wants to send %i bytes\n", datalen);
|
||||
char *buffer = (char*)malloc(sizeof(usbmux_tcp_header) + datalen + 2); // allow 2 bytes of safety padding
|
||||
// Set the length and pre-emptively htonl/htons it
|
||||
@@ -218,12 +223,12 @@ int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t da
|
||||
if (debug) printf("actually sending %zi bytes of data at %p\n", sizeof(usbmux_tcp_header)+datalen, buffer);
|
||||
|
||||
|
||||
bytes = send_to_phone(client->phone, buffer, sizeof(usbmux_tcp_header)+datalen);
|
||||
if (debug) printf("mux_send: sent %i bytes!\n", bytes);
|
||||
*sent_bytes = send_to_phone(client->phone, buffer, sizeof(usbmux_tcp_header)+datalen);
|
||||
if (debug) printf("mux_send: sent %i bytes!\n", *sent_bytes);
|
||||
// Now that we've sent it off, we can clean up after our sloppy selves.
|
||||
if (debug) {
|
||||
FILE *packet = fopen("packet", "a+");
|
||||
fwrite(buffer, 1, bytes, packet);
|
||||
fwrite(buffer, 1, *sent_bytes, packet);
|
||||
fclose(packet);
|
||||
printf("\n");
|
||||
}
|
||||
@@ -238,13 +243,14 @@ int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t da
|
||||
client->header->length16 = ntohs(client->header->length16);
|
||||
|
||||
// Now return the bytes.
|
||||
if (bytes < sizeof(usbmux_tcp_header)+datalen) {
|
||||
return -1; // blah
|
||||
if (*sent_bytes < sizeof(usbmux_tcp_header)+datalen) {
|
||||
*sent_bytes = 0;
|
||||
return IPHONE_E_NOT_ENOUGH_DATA;
|
||||
} else {
|
||||
return bytes - 28; // actual length sent. :/
|
||||
*sent_bytes = *sent_bytes - 28; // actual length sent. :/
|
||||
}
|
||||
|
||||
return bytes; // or something
|
||||
return IPHONE_E_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
/** This is a higher-level USBMuxTCP-like function
|
||||
@@ -255,7 +261,10 @@ int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t da
|
||||
*
|
||||
* @return How many bytes were read, or -1 if something bad happens.
|
||||
*/
|
||||
int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen ) {
|
||||
iphone_error_t iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen, uint32_t *recv_bytes ) {
|
||||
|
||||
if (!client || !data || datalen == 0 || !recv_bytes)
|
||||
return IPHONE_E_INVALID_ARG;
|
||||
/*
|
||||
* Order of operation:
|
||||
* 1.) Check if the client has a pre-received buffer.
|
||||
@@ -268,6 +277,7 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen
|
||||
*/
|
||||
if (debug) printf("mux_recv: datalen == %i\n", datalen);
|
||||
int bytes = 0, i = 0, complex = 0, offset = 0;
|
||||
*recv_bytes = 0;
|
||||
char *buffer = NULL;
|
||||
usbmux_tcp_header *header = NULL;
|
||||
|
||||
@@ -304,7 +314,7 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen
|
||||
if (bytes < 28) {
|
||||
free(buffer);
|
||||
if (debug) printf("mux_recv: Did not even get the header.\n");
|
||||
return -1;
|
||||
return IPHONE_E_NOT_ENOUGH_DATA;
|
||||
}
|
||||
|
||||
header = (usbmux_tcp_header*)buffer;
|
||||
@@ -332,7 +342,7 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen
|
||||
// Free our buffer and continue.
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
return iphone_mux_recv(client, data, datalen); // recurse back in to try again
|
||||
return iphone_mux_recv(client, data, datalen, recv_bytes); // recurse back in to try again
|
||||
}
|
||||
|
||||
// The packet was absolutely meant for us if it hits this point.
|
||||
@@ -348,13 +358,15 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen
|
||||
memcpy(client->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen);
|
||||
free(buffer);
|
||||
client->header->ocnt += bytes-28;
|
||||
return datalen;
|
||||
*recv_bytes = datalen;
|
||||
return IPHONE_E_SUCCESS;
|
||||
} else {
|
||||
// Fill the data with what we have, and just return.
|
||||
memcpy(data+offset, buffer+28, bytes-28); // data+offset: see #2b, above
|
||||
client->header->ocnt += bytes-28;
|
||||
free(buffer);
|
||||
return (bytes-28);
|
||||
*recv_bytes = bytes - 28;
|
||||
return IPHONE_E_SUCCESS;
|
||||
}
|
||||
|
||||
// If we get to this point, 'tis probably bad.
|
||||
|
||||
Reference in New Issue
Block a user