summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Martin Szulecki2009-07-07 17:58:48 +0200
committerGravatar Martin Szulecki2009-07-07 17:58:48 +0200
commitc9fd7ad7b49ed65ffae316ca19f54d54c5d6e320 (patch)
treeb6da02e07209829f9d17f572829978535ab3671b
parentb9ded23b93310b52843a18c07c176536e44445b5 (diff)
parent6de08b1e12946b85a595f82c1c04391d70d8b828 (diff)
downloadlibimobiledevice-c9fd7ad7b49ed65ffae316ca19f54d54c5d6e320.tar.gz
libimobiledevice-c9fd7ad7b49ed65ffae316ca19f54d54c5d6e320.tar.bz2
Merge branch 'master' of git://github.com/MattColyer/libiphone into martin
-rw-r--r--dev/afccheck.c4
-rw-r--r--dev/main.c27
-rw-r--r--include/libiphone/libiphone.h26
-rw-r--r--src/AFC.c264
-rw-r--r--src/AFC.h11
5 files changed, 149 insertions, 183 deletions
diff --git a/dev/afccheck.c b/dev/afccheck.c
index 2f7d92c..965981b 100644
--- a/dev/afccheck.c
+++ b/dev/afccheck.c
@@ -50,13 +50,13 @@ void check_afc(gpointer data)
}
//now writes buffer on iphone
- iphone_afc_file_t file = NULL;
+ uint64_t file = 0;
char path[50];
sprintf(path, "/Buf%i", ((param *) data)->id);
iphone_afc_open_file(((param *) data)->afc, path, AFC_FOPEN_RW, &file);
iphone_afc_write_file(((param *) data)->afc, file, (char *) buf, buffersize, &bytes);
iphone_afc_close_file(((param *) data)->afc, file);
- file = NULL;
+ file = 0;
if (bytes != buffersize)
printf("Write operation failed\n");
diff --git a/dev/main.c b/dev/main.c
index 5c9a5a7..c8c9dfa 100644
--- a/dev/main.c
+++ b/dev/main.c
@@ -59,7 +59,7 @@ int main(int argc, char *argv[])
int npp;
iphone_lckd_client_t control = NULL;
iphone_device_t phone = NULL;
- iphone_afc_file_t lockfile = NULL;
+ uint64_t lockfile = 0;
iphone_np_client_t gnp = NULL;
if (argc > 1 && !strcasecmp(argv[1], "--debug")) {
@@ -148,14 +148,23 @@ int main(int argc, char *argv[])
}
g_strfreev(dirs);
- iphone_afc_file_t my_file = NULL;
- struct stat stbuf;
- iphone_afc_get_file_attr(afc, "/iTunesOnTheGoPlaylist.plist", &stbuf);
+ uint64_t my_file = 0;
+ char **info = NULL;
+ uint64_t fsize = 0;
+ if (IPHONE_E_SUCCESS == iphone_afc_get_file_info(afc, "/readme.libiphone.fx", &info) && info) {
+ for (i = 0; info[i]; i += 2) {
+ printf("%s: %s\n", info[i], info[i+1]);
+ if (!strcmp(info[i], "st_size")) {
+ fsize = atoll(info[i+1]);
+ }
+ }
+ }
+
if (IPHONE_E_SUCCESS ==
- iphone_afc_open_file(afc, "/iTunesOnTheGoPlaylist.plist", AFC_FOPEN_RDONLY, &my_file) && my_file) {
- printf("A file size: %i\n", (int) stbuf.st_size);
- char *file_data = (char *) malloc(sizeof(char) * stbuf.st_size);
- iphone_afc_read_file(afc, my_file, file_data, stbuf.st_size, &bytes);
+ iphone_afc_open_file(afc, "/readme.libiphone.fx", AFC_FOPEN_RDONLY, &my_file) && my_file) {
+ printf("A file size: %i\n", fsize);
+ char *file_data = (char *) malloc(sizeof(char) * fsize);
+ iphone_afc_read_file(afc, my_file, file_data, fsize, &bytes);
if (bytes >= 0) {
printf("The file's data:\n");
fwrite(file_data, 1, bytes, stdout);
@@ -193,7 +202,7 @@ int main(int argc, char *argv[])
printf("Seek & read\n");
iphone_afc_open_file(afc, "/readme.libiphone.fx", AFC_FOPEN_RDONLY, &my_file);
- if (IPHONE_E_SUCCESS != iphone_afc_seek_file(afc, my_file, 5))
+ if (IPHONE_E_SUCCESS != iphone_afc_seek_file(afc, my_file, 5, SEEK_CUR))
printf("WARN: SEEK DID NOT WORK\n");
char *threeletterword = (char *) malloc(sizeof(char) * 5);
iphone_afc_read_file(afc, my_file, threeletterword, 3, &bytes);
diff --git a/include/libiphone/libiphone.h b/include/libiphone/libiphone.h
index bd8d9fb..463efa7 100644
--- a/include/libiphone/libiphone.h
+++ b/include/libiphone/libiphone.h
@@ -63,6 +63,11 @@ typedef enum {
AFC_FOPEN_RDAPPEND = 0x00000006 // a+ O_RDWR | O_APPEND | O_CREAT
} iphone_afc_file_mode_t;
+typedef enum {
+ IPHONE_AFC_HARDLINK = 1,
+ IPHONE_AFC_SYMLINK = 2
+} iphone_afc_link_type_t;
+
struct iphone_device_int;
typedef struct iphone_device_int *iphone_device_t;
@@ -72,9 +77,6 @@ typedef struct iphone_lckd_client_int *iphone_lckd_client_t;
struct iphone_afc_client_int;
typedef struct iphone_afc_client_int *iphone_afc_client_t;
-struct iphone_afc_file_int;
-typedef struct iphone_afc_file_int *iphone_afc_file_t;
-
struct iphone_msync_client_int;
typedef struct iphone_msync_client_int *iphone_msync_client_t;
@@ -118,19 +120,19 @@ int iphone_afc_get_errno ( iphone_afc_client_t client );
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);
-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, iphone_afc_file_mode_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_lock_file ( iphone_afc_client_t client, iphone_afc_file_t file, int operation);
-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_get_file_info ( iphone_afc_client_t client, const char *filename, char ***infolist );
+iphone_error_t iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, iphone_afc_file_mode_t file_mode, uint64_t *handle );
+iphone_error_t iphone_afc_close_file ( iphone_afc_client_t client, uint64_t handle);
+iphone_error_t iphone_afc_lock_file ( iphone_afc_client_t client, uint64_t handle, int operation);
+iphone_error_t iphone_afc_read_file ( iphone_afc_client_t client, uint64_t handle, char *data, int length, uint32_t *bytes);
+iphone_error_t iphone_afc_write_file ( iphone_afc_client_t client, uint64_t handle, const char *data, int length, uint32_t *bytes);
+iphone_error_t iphone_afc_seek_file ( iphone_afc_client_t client, uint64_t handle, int64_t offset, int whence);
+iphone_error_t iphone_afc_truncate_file ( iphone_afc_client_t client, uint64_t handle, uint64_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);
iphone_error_t iphone_afc_truncate(iphone_afc_client_t client, const char *path, off_t newsize);
-
+iphone_error_t iphone_afc_make_link ( iphone_afc_client_t client, iphone_afc_link_type_t linktype, const char *target, const char *linkname);
iphone_error_t iphone_msync_new_client(iphone_device_t device, int dst_port,
diff --git a/src/AFC.c b/src/AFC.c
index abaeb3f..960d640 100644
--- a/src/AFC.c
+++ b/src/AFC.c
@@ -225,7 +225,7 @@ static int dispatch_AFC_packet(iphone_afc_client_t client, const char *data, uin
client->afc_packet->packet_num++;
if (!client->afc_packet->entire_length) {
- client->afc_packet->entire_length = (length) ? sizeof(AFCPacket) + length + 1 : sizeof(AFCPacket);
+ client->afc_packet->entire_length = (length) ? sizeof(AFCPacket) + length : sizeof(AFCPacket);
client->afc_packet->this_length = client->afc_packet->entire_length;
}
if (!client->afc_packet->this_length) {
@@ -270,7 +270,6 @@ static int dispatch_AFC_packet(iphone_afc_client_t client, const char *data, uin
log_debug_msg("dispatch_AFC_packet packet data follows\n");
if (length > 0) {
memcpy(buffer + sizeof(AFCPacket), data, length);
- buffer[sizeof(AFCPacket) + length] = '\0';
}
log_debug_buffer(buffer, client->afc_packet->this_length);
log_debug_msg("\n");
@@ -484,7 +483,7 @@ iphone_error_t iphone_afc_get_dir_list(iphone_afc_client_t client, const char *d
client->afc_packet->operation = AFC_LIST_DIR;
client->afc_packet->entire_length = 0;
client->afc_packet->this_length = 0;
- bytes = dispatch_AFC_packet(client, dir, strlen(dir));
+ bytes = dispatch_AFC_packet(client, dir, strlen(dir)+1);
if (bytes <= 0) {
afc_unlock(client);
return IPHONE_E_NOT_ENOUGH_DATA;
@@ -570,7 +569,7 @@ iphone_error_t iphone_afc_delete_file(iphone_afc_client_t client, const char *pa
// Send command
client->afc_packet->this_length = client->afc_packet->entire_length = 0;
client->afc_packet->operation = AFC_DELETE;
- bytes = dispatch_AFC_packet(client, path, strlen(path));
+ bytes = dispatch_AFC_packet(client, path, strlen(path)+1);
if (bytes <= 0) {
afc_unlock(client);
return IPHONE_E_NOT_ENOUGH_DATA;
@@ -613,7 +612,7 @@ iphone_error_t iphone_afc_rename_file(iphone_afc_client_t client, const char *fr
memcpy(send + strlen(from) + 1, to, strlen(to) + 1);
client->afc_packet->entire_length = client->afc_packet->this_length = 0;
client->afc_packet->operation = AFC_RENAME;
- bytes = dispatch_AFC_packet(client, send, strlen(to) + strlen(from) + 2);
+ bytes = dispatch_AFC_packet(client, send, strlen(to)+1 + strlen(from)+1);
free(send);
if (bytes <= 0) {
afc_unlock(client);
@@ -654,7 +653,7 @@ iphone_error_t iphone_afc_mkdir(iphone_afc_client_t client, const char *dir)
// Send command
client->afc_packet->operation = AFC_MAKE_DIR;
client->afc_packet->this_length = client->afc_packet->entire_length = 0;
- bytes = dispatch_AFC_packet(client, dir, strlen(dir));
+ bytes = dispatch_AFC_packet(client, dir, strlen(dir)+1);
if (bytes <= 0) {
afc_unlock(client);
return IPHONE_E_NOT_ENOUGH_DATA;
@@ -676,102 +675,42 @@ iphone_error_t iphone_afc_mkdir(iphone_afc_client_t client, const char *dir)
*
* @param client The client to use to get the information of the file.
* @param path The fully-qualified path to the file.
+ * @param infolist Pointer to a buffer that will be filled with a NULL-terminated
+ * list of strings with the file information.
+ * Set to NULL before calling this function.
*
- * @return A pointer to an AFCFile struct containing the information received,
- * or NULL on failure.
+ * @return IPHONE_E_SUCCESS on success or an IPHONE_E_* error value
+ * when something went wrong.
*/
-static iphone_afc_file_t afc_get_file_info(iphone_afc_client_t client, const char *path)
+iphone_error_t iphone_afc_get_file_info(iphone_afc_client_t client, const char *path, char ***infolist)
{
- char *received, **list;
- iphone_afc_file_t my_file;
- int length, i = 0;
+ char *received = NULL;
+ int length;
+
+ if (!client || !path || !infolist) {
+ return IPHONE_E_INVALID_ARG;
+ }
afc_lock(client);
// Send command
client->afc_packet->operation = AFC_GET_INFO;
client->afc_packet->entire_length = client->afc_packet->this_length = 0;
- dispatch_AFC_packet(client, path, strlen(path));
+ dispatch_AFC_packet(client, path, strlen(path)+1);
// Receive data
length = receive_AFC_data(client, &received);
if (received) {
- list = make_strings_list(received, length);
+ *infolist = make_strings_list(received, length);
free(received);
} else {
afc_unlock(client);
- return NULL;
+ return IPHONE_E_AFC_ERROR;
}
afc_unlock(client);
- // Parse the data
- if (list) {
- my_file = (iphone_afc_file_t) malloc(sizeof(struct iphone_afc_file_int));
- for (i = 0; list[i]; i++) {
- if (!strcmp(list[i], "st_size")) {
- my_file->size = atoll(list[i + 1]);
- }
-
- if (!strcmp(list[i], "st_blocks")) {
- my_file->blocks = atoi(list[i + 1]);
- }
-
- if (!strcmp(list[i], "st_ifmt")) {
- if (!strcmp(list[i + 1], "S_IFREG")) {
- my_file->mode = S_IFREG;
- } else if (!strcmp(list[i + 1], "S_IFDIR")) {
- my_file->mode = S_IFDIR;
- } else if (!strcmp(list[i + 1], "S_IFLNK")) {
- my_file->mode = S_IFLNK;
- }
- }
-
- if (!strcmp(list[i], "st_nlink")) {
- my_file->nlink = atoi(list[i + 1]);
- }
- }
- g_strfreev(list);
- return my_file;
- } else {
- return NULL;
- }
-}
-
-/** Gets information about a specific file.
- *
- * @param client The client to use to get the information of the file.
- * @param path The fully-qualified path to the file
- * @param stbuf output buffer where file information will be stored
- *
- * @return A pointer to an AFCFile struct containing the information received,
- * or NULL on failure.
- */
-iphone_error_t iphone_afc_get_file_attr(iphone_afc_client_t client, const char *filename, struct stat * stbuf)
-{
-
- iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
- if (!client || client->sfd < 0 || !client->afc_packet || !stbuf)
- return IPHONE_E_INVALID_ARG;
-
- memset(stbuf, 0, sizeof(struct stat));
- iphone_afc_file_t file = afc_get_file_info(client, filename);
- if (!file) {
- ret = IPHONE_E_AFC_ERROR;
- } else {
- stbuf->st_mode = file->mode | (S_ISDIR(file->mode) ? 0755 : (S_ISLNK(file->mode) ? 0777 : 0644));
- stbuf->st_size = file->size;
- stbuf->st_blksize = 2048; // FIXME: Is this the actual block
- // size used on the iPhone?
- stbuf->st_blocks = file->blocks;
- stbuf->st_nlink = file->nlink;
- stbuf->st_uid = getuid();
- stbuf->st_gid = getgid();
-
- free(file);
- ret = IPHONE_E_SUCCESS;
- }
- return ret;
+ return IPHONE_E_SUCCESS;
}
/** Opens a file on the phone.
@@ -782,20 +721,21 @@ iphone_error_t iphone_afc_get_file_attr(iphone_afc_client_t client, const char *
* AFC_FILE_WRITE; the former lets you read and write,
* however, and the second one will *create* the file,
* destroying anything previously there.
+ * @param handle Pointer to a uint64_t that will hold the handle of the file
*
- * @return A pointer to an AFCFile struct containing the file information (as
- * received by afc_get_file_info) as well as the handle to the file or
- * NULL in the case of failure.
+ * @return IPHONE_E_SUCCESS on success or an IPHONE_E_* error on failure.
*/
iphone_error_t
iphone_afc_open_file(iphone_afc_client_t client, const char *filename,
- iphone_afc_file_mode_t file_mode, iphone_afc_file_t * file)
+ iphone_afc_file_mode_t file_mode, uint64_t *handle)
{
- iphone_afc_file_t file_loc = NULL;
uint32_t ag = 0;
int bytes = 0, length = 0;
char *data = (char *) malloc(sizeof(char) * (8 + strlen(filename) + 1));
+ // set handle to 0 so in case an error occurs, the handle is invalid
+ *handle = 0;
+
if (!client || client->sfd < 0|| !client->afc_packet)
return IPHONE_E_INVALID_ARG;
@@ -808,7 +748,7 @@ iphone_afc_open_file(iphone_afc_client_t client, const char *filename,
data[8 + strlen(filename)] = '\0';
client->afc_packet->operation = AFC_FILE_OPEN;
client->afc_packet->entire_length = client->afc_packet->this_length = 0;
- bytes = dispatch_AFC_packet(client, data, 8 + strlen(filename));
+ bytes = dispatch_AFC_packet(client, data, 8 + strlen(filename) + 1);
free(data);
if (bytes <= 0) {
@@ -821,11 +761,9 @@ iphone_afc_open_file(iphone_afc_client_t client, const char *filename,
if (length > 0 && data) {
afc_unlock(client);
- // Get the file info and return it
- file_loc = afc_get_file_info(client, filename);
- memcpy(&file_loc->filehandle, data, 4);
+ // Get the file handle
+ memcpy(handle, data, sizeof(uint64_t));
free(data);
- *file = file_loc;
return IPHONE_E_SUCCESS;
} else {
log_debug_msg("afc_open_file: Didn't get any further data\n");
@@ -841,20 +779,20 @@ iphone_afc_open_file(iphone_afc_client_t client, const char *filename,
/** Attempts to the read the given number of bytes from the given file.
*
* @param client The relevant AFC client
- * @param file The AFCFile to read from
+ * @param handle File handle of a previously opened file
* @param data The pointer to the memory region to store the read data
* @param length The number of bytes to read
*
* @return The number of bytes read if successful. If there was an error -1.
*/
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_afc_read_file(iphone_afc_client_t client, uint64_t handle, char *data, int length, uint32_t * bytes)
{
char *input = NULL;
int current_count = 0, bytes_loc = 0;
const int MAXIMUM_READ_SIZE = 1 << 16;
- if (!client || !client->afc_packet || client->sfd < 0 || !file)
+ if (!client || !client->afc_packet || client->sfd < 0 || handle == 0)
return IPHONE_E_INVALID_ARG;
log_debug_msg("afc_read_file called for length %i\n", length);
@@ -867,7 +805,7 @@ iphone_afc_read_file(iphone_afc_client_t client, iphone_afc_file_t file, char *d
// Send the read command
AFCFilePacket *packet = (AFCFilePacket *) malloc(sizeof(AFCFilePacket));
- packet->filehandle = file->filehandle;
+ packet->filehandle = handle;
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;
@@ -911,7 +849,7 @@ iphone_afc_read_file(iphone_afc_client_t client, iphone_afc_file_t file, char *d
/** Writes a given number of bytes to a file.
*
* @param client The client to use to write to the file.
- * @param file A pointer to an AFCFile struct; serves as the file handle.
+ * @param handle File handle of previously opened file.
* @param data The data to write to the file.
* @param length How much data to write.
*
@@ -919,7 +857,7 @@ iphone_afc_read_file(iphone_afc_client_t client, iphone_afc_file_t file, char *d
* none were written...
*/
iphone_error_t
-iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file,
+iphone_afc_write_file(iphone_afc_client_t client, uint64_t handle,
const char *data, int length, uint32_t * bytes)
{
char *acknowledgement = NULL;
@@ -929,7 +867,7 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file,
int bytes_loc = 0;
char *out_buffer = NULL;
- if (!client || !client->afc_packet || client->sfd < 0 || !file || !bytes)
+ if (!client || !client->afc_packet || client->sfd < 0 || !bytes || (handle == 0))
return IPHONE_E_INVALID_ARG;
afc_lock(client);
@@ -943,8 +881,7 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file,
client->afc_packet->entire_length = client->afc_packet->this_length + MAXIMUM_WRITE_SIZE;
client->afc_packet->operation = AFC_WRITE;
out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket));
- memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32_t));
- memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32_t));
+ memcpy(out_buffer, (char *)&handle, sizeof(uint64_t));
memcpy(out_buffer + 8, data + current_count, MAXIMUM_WRITE_SIZE);
bytes_loc = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8);
if (bytes_loc < 0) {
@@ -978,8 +915,7 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file,
client->afc_packet->entire_length = client->afc_packet->this_length + (length - current_count);
client->afc_packet->operation = AFC_WRITE;
out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket));
- memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32_t));
- memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32_t));
+ memcpy(out_buffer, (char *) &handle, sizeof(uint64_t));
memcpy(out_buffer + 8, data + current_count, (length - current_count));
bytes_loc = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8);
free(out_buffer);
@@ -1008,27 +944,24 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file,
/** Closes a file on the phone.
*
* @param client The client to close the file with.
- * @param file A pointer to an AFCFile struct containing the file handle of the
- * file to close.
+ * @param handle File handle of a previously opened file.
*/
-iphone_error_t 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, uint64_t handle)
{
- if (!client || !file)
+ if (!client || (handle == 0))
return IPHONE_E_INVALID_ARG;
char *buffer = malloc(sizeof(char) * 8);
- uint32_t zero = 0;
int bytes = 0;
afc_lock(client);
- log_debug_msg("afc_close_file: File handle %i\n", file->filehandle);
+ log_debug_msg("afc_close_file: File handle %i\n", handle);
// Send command
- memcpy(buffer, &file->filehandle, sizeof(uint32_t));
- memcpy(buffer + sizeof(uint32_t), &zero, sizeof(zero));
+ memcpy(buffer, &handle, sizeof(uint64_t));
client->afc_packet->operation = AFC_FILE_CLOSE;
client->afc_packet->entire_length = client->afc_packet->this_length = 0;
- bytes = dispatch_AFC_packet(client, buffer, sizeof(char) * 8);
+ bytes = dispatch_AFC_packet(client, buffer, 8);
free(buffer);
buffer = NULL;
@@ -1044,7 +977,6 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file
bytes = receive_AFC_data(client, &buffer);
if (buffer)
free(buffer);
- free(file);
afc_unlock(client);
return IPHONE_E_SUCCESS;
}
@@ -1062,31 +994,28 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file
* LOCK_UN 8 // unlock
*
* @param client The client to close the file with.
- * @param file A pointer to an AFCFile struct containing the file handle of the
- * file to close.
+ * @param handle File handle of a previously opened file.
* @operation the lock or unlock operation to perform.
*/
-iphone_error_t iphone_afc_lock_file(iphone_afc_client_t client, iphone_afc_file_t file, int operation)
+iphone_error_t iphone_afc_lock_file(iphone_afc_client_t client, uint64_t handle, int operation)
{
- if (!client || !file)
+ if (!client || (handle == 0))
return IPHONE_E_INVALID_ARG;
char *buffer = malloc(16);
- uint32_t zero = 0;
int bytes = 0;
uint64_t op = operation;
afc_lock(client);
- log_debug_msg("afc_lock_file: File handle %i\n", file->filehandle);
+ log_debug_msg("afc_lock_file: File handle %i\n", handle);
// Send command
- memcpy(buffer, &file->filehandle, sizeof(uint32_t));
- memcpy(buffer + sizeof(uint32_t), &zero, sizeof(zero));
+ memcpy(buffer, &handle, sizeof(uint64_t));
memcpy(buffer + 8, &op, 8);
client->afc_packet->operation = AFC_FILE_LOCK;
client->afc_packet->entire_length = client->afc_packet->this_length = 0;
- bytes = dispatch_AFC_packet(client, buffer, 15);
+ bytes = dispatch_AFC_packet(client, buffer, 16);
free(buffer);
buffer = NULL;
@@ -1111,34 +1040,28 @@ iphone_error_t iphone_afc_lock_file(iphone_afc_client_t client, iphone_afc_file_
/** Seeks to a given position of a pre-opened file on the phone.
*
* @param client The client to use to seek to the position.
- * @param file The file to seek to a position on.
- * @param seekpos Where to seek to. If passed a negative value, this will seek
- * from the end of the file.
+ * @param handle File handle of a previously opened.
+ * @param offset Seek offset.
+ * @param whence Seeking direction, one of SEEK_SET, SEEK_CUR, or SEEK_END.
*
* @return IPHONE_E_SUCCESS on success, IPHONE_E_NOT_ENOUGH_DATA on failure.
*/
-iphone_error_t 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, uint64_t handle, int64_t offset, int whence)
{
char *buffer = (char *) malloc(sizeof(char) * 24);
- uint32_t seekto = 0, zero = 0;
+ uint32_t zero = 0;
int bytes = 0;
- if (seekpos < 0)
- seekpos = file->size - abs(seekpos);
-
afc_lock(client);
// Send the command
- seekto = seekpos;
- memcpy(buffer, &file->filehandle, sizeof(uint32_t)); // handle
- memcpy(buffer + 4, &zero, sizeof(uint32_t)); // pad
- memcpy(buffer + 8, &zero, sizeof(uint32_t)); // fromwhere
+ memcpy(buffer, &handle, sizeof(uint64_t)); // handle
+ memcpy(buffer + 8, &whence, sizeof(int32_t)); // fromwhere
memcpy(buffer + 12, &zero, sizeof(uint32_t)); // pad
- memcpy(buffer + 16, &seekto, sizeof(uint32_t)); // offset
- memcpy(buffer + 20, &zero, sizeof(uint32_t)); // pad
+ memcpy(buffer + 16, &offset, sizeof(uint64_t)); // offset
client->afc_packet->operation = AFC_FILE_SEEK;
client->afc_packet->this_length = client->afc_packet->entire_length = 0;
- bytes = dispatch_AFC_packet(client, buffer, 23);
+ bytes = dispatch_AFC_packet(client, buffer, 24);
free(buffer);
buffer = NULL;
@@ -1162,7 +1085,7 @@ iphone_error_t iphone_afc_seek_file(iphone_afc_client_t client, iphone_afc_file_
/** Sets the size of a file on the phone.
*
* @param client The client to use to set the file size.
- * @param file The (pre-opened) file to set the size on.
+ * @param handle File handle of a previously opened file.
* @param newsize The size to set the file to.
*
* @return 0 on success, -1 on failure.
@@ -1170,22 +1093,19 @@ iphone_error_t iphone_afc_seek_file(iphone_afc_client_t client, iphone_afc_file_
* @note This function is more akin to ftruncate than truncate, and truncate
* calls would have to open the file before calling this, sadly.
*/
-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_truncate_file(iphone_afc_client_t client, uint64_t handle, uint64_t newsize)
{
char *buffer = (char *) malloc(sizeof(char) * 16);
int bytes = 0;
- uint32_t zero = 0;
afc_lock(client);
// Send command
- memcpy(buffer, &file->filehandle, sizeof(uint32_t)); // handle
- memcpy(buffer + 4, &zero, sizeof(uint32_t)); // pad
- memcpy(buffer + 8, &newsize, sizeof(uint32_t)); // newsize
- memcpy(buffer + 12, &zero, 3); // pad
+ memcpy(buffer, &handle, sizeof(uint64_t)); // handle
+ memcpy(buffer + 8, &newsize, sizeof(uint64_t)); // newsize
client->afc_packet->operation = AFC_FILE_TRUNCATE;
client->afc_packet->this_length = client->afc_packet->entire_length = 0;
- bytes = dispatch_AFC_packet(client, buffer, 15);
+ bytes = dispatch_AFC_packet(client, buffer, 16);
free(buffer);
buffer = NULL;
@@ -1232,7 +1152,7 @@ iphone_error_t iphone_afc_truncate(iphone_afc_client_t client, const char *path,
memcpy(send + 8, path, strlen(path) + 1);
client->afc_packet->entire_length = client->afc_packet->this_length = 0;
client->afc_packet->operation = AFC_TRUNCATE;
- bytes = dispatch_AFC_packet(client, send, 8 + strlen(path));
+ bytes = dispatch_AFC_packet(client, send, 8 + strlen(path) + 1);
free(send);
if (bytes <= 0) {
afc_unlock(client);
@@ -1251,8 +1171,54 @@ iphone_error_t iphone_afc_truncate(iphone_afc_client_t client, const char *path,
return IPHONE_E_SUCCESS;
}
-
-uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file)
+/** Creates a hard link or symbolic link on the device.
+ *
+ * @param client The client to use for making a link
+ * @param type 1 = hard link, 2 = symlink
+ * @param target The file to be linked.
+ * @param linkname The name of link.
+ *
+ * @return IPHONE_E_SUCCESS if everything went well, IPHONE_E_INVALID_ARG
+ * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise.
+ */
+iphone_error_t iphone_afc_make_link(iphone_afc_client_t client, iphone_afc_link_type_t linktype, const char *target, const char *linkname)
{
- return file->filehandle;
+ char *response = NULL;
+ char *send = (char *) malloc(sizeof(char) * (strlen(target)+1 + strlen(linkname)+1 + 8));
+ int bytes = 0;
+ uint64_t type = linktype;
+
+ if (!client || !target || !linkname || !client->afc_packet || client->sfd < 0)
+ return IPHONE_E_INVALID_ARG;
+
+ afc_lock(client);
+
+ log_debug_msg("link type: %lld\n", type);
+ log_debug_msg("target: %s, length:%d\n", target, strlen(target));
+ log_debug_msg("linkname: %s, length:%d\n", linkname, strlen(linkname));
+
+ // Send command
+ memcpy(send, &type, 8);
+ memcpy(send + 8, target, strlen(target) + 1);
+ memcpy(send + 8 + strlen(target) + 1, linkname, strlen(linkname) + 1);
+ client->afc_packet->entire_length = client->afc_packet->this_length = 0;
+ client->afc_packet->operation = AFC_MAKE_LINK;
+ bytes = dispatch_AFC_packet(client, send, 8 + strlen(linkname) + 1 + strlen(target) + 1);
+ free(send);
+ if (bytes <= 0) {
+ afc_unlock(client);
+ return IPHONE_E_NOT_ENOUGH_DATA;
+ }
+ // Receive response
+ bytes = receive_AFC_data(client, &response);
+ if (response)
+ free(response);
+
+ afc_unlock(client);
+
+ if (bytes < 0) {
+ return IPHONE_E_NOT_ENOUGH_DATA;
+ } else {
+ return IPHONE_E_SUCCESS;
+ }
}
diff --git a/src/AFC.h b/src/AFC.h
index 5827518..a9c33c3 100644
--- a/src/AFC.h
+++ b/src/AFC.h
@@ -55,16 +55,6 @@ struct iphone_afc_client_int {
GMutex *mutex;
};
-struct iphone_afc_file_int {
- uint32_t filehandle;
- uint32_t blocks;
- off_t size;
- uint32_t mode;
- uint32_t nlink;
-};
-
-
-
enum {
AFC_ERROR = 0x00000001,
AFC_SUCCESS_RESPONSE = 0x00000002,
@@ -96,5 +86,4 @@ enum {
AFC_MAKE_LINK = 0x0000001C // MakeLink
};
-uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file);
static int afcerror_to_errno(int afcerror);