diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ifuse.c | 184 | 
1 files changed, 133 insertions, 51 deletions
| diff --git a/src/ifuse.c b/src/ifuse.c index 0aac298..d8c6ddc 100644 --- a/src/ifuse.c +++ b/src/ifuse.c @@ -35,21 +35,36 @@ typedef uint32_t uint32;		// this annoys me too  #include <libiphone/libiphone.h> -GHashTable *file_handles; -int fh_index = 0; +int g_blocksize = 4096; // assume this is the default block size  iphone_device_t phone = NULL;  iphone_lckd_client_t control = NULL;  int debug = 0; +static void free_dictionary(char **dictionary) +{ +	int i = 0; + +	if (!dictionary) +		return; + +	for (i = 0; dictionary[i]; i++) { +		free(dictionary[i]); +	} +	free(dictionary); +} +  static int ifuse_getattr(const char *path, struct stat *stbuf)  { +	int i;  	int res = 0; +	char **info = NULL;  	iphone_afc_client_t afc = fuse_get_context()->private_data; -	iphone_error_t ret = iphone_afc_get_file_attr(afc, path, stbuf); +	iphone_error_t ret = iphone_afc_get_file_info(afc, path, &info); +	memset(stbuf, 0, sizeof(struct stat));  	if (ret == IPHONE_E_AFC_ERROR) {  		int e = iphone_afc_get_errno(afc);  		if (e < 0) { @@ -59,22 +74,54 @@ static int ifuse_getattr(const char *path, struct stat *stbuf)  		}  	} else if (ret != IPHONE_E_SUCCESS) {  		res = -EACCES; -	} - -	return res; -} +	} else if (!info) { +		res = -1; +	} else { +		// get file attributes from info list +		for (i = 0; info[i]; i += 2) { +			if (!strcmp(info[i], "st_size")) { +				stbuf->st_size = atoll(info[i+1]); +			} else if (!strcmp(info[i], "st_blocks")) { +				stbuf->st_blocks = atoi(info[i+1]); +			} else if (!strcmp(info[i], "st_ifmt")) { +				if (!strcmp(info[i+1], "S_IFREG")) { +					stbuf->st_mode = S_IFREG; +				} else if (!strcmp(info[i+1], "S_IFDIR")) { +					stbuf->st_mode = S_IFDIR; +				} else if (!strcmp(info[i+1], "S_IFLNK")) { +					stbuf->st_mode = S_IFLNK; +				} else if (!strcmp(info[i+1], "S_IFBLK")) { +					stbuf->st_mode = S_IFBLK; +				} else if (!strcmp(info[i+1], "S_IFCHR")) { +					stbuf->st_mode = S_IFCHR; +				} else if (!strcmp(info[i+1], "S_IFIFO")) { +					stbuf->st_mode = S_IFIFO; +				} else if (!strcmp(info[i+1], "S_IFSOCK")) { +					stbuf->st_mode = S_IFSOCK; +				} +			} else if (!strcmp(info[i], "st_nlink")) { +				stbuf->st_nlink = atoi(info[i+1]); +			} +		} +		free_dictionary(info); -static void free_dictionary(char **dictionary) -{ -	int i = 0; +		// set permission bits according to the file type +		if (S_ISDIR(stbuf->st_mode)) { +			stbuf->st_mode |= 0755; +		} else if (S_ISLNK(stbuf->st_mode)) { +			stbuf->st_mode |= 0777; +		} else { +	    		stbuf->st_mode |= 0644; +		} -	if (!dictionary) -		return; +		// and set some additional info +		stbuf->st_uid = getuid(); +		stbuf->st_gid = getgid(); -	for (i = 0; dictionary[i]; i++) { -		free(dictionary[i]); +		stbuf->st_blksize = g_blocksize;  	} -	free(dictionary); + +	return res;  }  static int ifuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) @@ -131,17 +178,16 @@ static int get_afc_file_mode(iphone_afc_file_mode_t *afc_mode, int flags)  static int ifuse_open(const char *path, struct fuse_file_info *fi)  { -	iphone_afc_file_t file = NULL; +	int i;  	iphone_afc_client_t afc = fuse_get_context()->private_data;  	iphone_error_t err;          iphone_afc_file_mode_t mode = 0; -	uint32 *argh_filehandle = (uint32 *) malloc(sizeof(uint32));  	if (get_afc_file_mode(&mode, fi->flags) < 0 || (mode == 0)) {  		return -EPERM;  	} -	err = iphone_afc_open_file(afc, path, mode, &file); +	err = iphone_afc_open_file(afc, path, mode, &fi->fh);  	if (err == IPHONE_E_AFC_ERROR) {  		int res = iphone_afc_get_errno(afc);  		if (res < 0) { @@ -153,10 +199,6 @@ static int ifuse_open(const char *path, struct fuse_file_info *fi)  		return -EINVAL;  	} -	*argh_filehandle = iphone_afc_get_file_handle(file); -	fi->fh = *argh_filehandle; -	g_hash_table_insert(file_handles, argh_filehandle, file); -  	return 0;  } @@ -168,37 +210,26 @@ static int ifuse_create(const char *path, mode_t mode, struct fuse_file_info *fi  static int ifuse_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)  {  	int bytes = 0; -	iphone_afc_file_t file;  	iphone_afc_client_t afc = fuse_get_context()->private_data;  	if (size == 0)  		return 0; -	file = g_hash_table_lookup(file_handles, &(fi->fh)); -	if (!file) { -		return -ENOENT; -	} - -	if (IPHONE_E_SUCCESS == iphone_afc_seek_file(afc, file, offset)) -		iphone_afc_read_file(afc, file, buf, size, &bytes); +	if (IPHONE_E_SUCCESS == iphone_afc_seek_file(afc, fi->fh, offset, SEEK_SET)) +		iphone_afc_read_file(afc, fi->fh, buf, size, &bytes);  	return bytes;  }  static int ifuse_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi)  {  	int bytes = 0; -	iphone_afc_file_t file = NULL;  	iphone_afc_client_t afc = fuse_get_context()->private_data;  	if (size == 0)  		return 0; -	file = g_hash_table_lookup(file_handles, &(fi->fh)); -	if (!file) -		return -ENOENT; - -	if (IPHONE_E_SUCCESS == iphone_afc_seek_file(afc, file, offset)) -		iphone_afc_write_file(afc, file, buf, size, &bytes); +	if (IPHONE_E_SUCCESS == iphone_afc_seek_file(afc, fi->fh, offset, SEEK_SET)) +		iphone_afc_write_file(afc, fi->fh, buf, size, &bytes);  	return bytes;  } @@ -209,16 +240,9 @@ static int ifuse_fsync(const char *path, int datasync, struct fuse_file_info *fi  static int ifuse_release(const char *path, struct fuse_file_info *fi)  { -	iphone_afc_file_t file = NULL;  	iphone_afc_client_t afc = fuse_get_context()->private_data; -	file = g_hash_table_lookup(file_handles, &(fi->fh)); -	if (!file) { -		return -ENOENT; -	} -	iphone_afc_close_file(afc, file); - -	g_hash_table_remove(file_handles, &(fi->fh)); +	iphone_afc_close_file(afc, fi->fh);  	return 0;  } @@ -230,8 +254,6 @@ void *ifuse_init_with_service(struct fuse_conn_info *conn, const char *service_n  	conn->async_read = 0; -	file_handles = g_hash_table_new(g_int_hash, g_int_equal); -  	if (IPHONE_E_SUCCESS == iphone_lckd_start_service(control, service_name, &port) && !port) {  		iphone_lckd_free_client(control);  		iphone_free_device(phone); @@ -244,6 +266,21 @@ void *ifuse_init_with_service(struct fuse_conn_info *conn, const char *service_n  	iphone_lckd_free_client(control);  	control = NULL; +	if (afc) { +		// get file system block size +		int i; +		char **info_raw = NULL; +		if ((IPHONE_E_SUCCESS == iphone_afc_get_devinfo(afc, &info_raw)) && info_raw) { +			for (i = 0; info_raw[i]; i+=2) { +				if (!strcmp(info_raw[i], "FSBlockSize")) { +					g_blocksize = atoi(info_raw[i + 1]); +					break; +				} +			} +			free_dictionary(info_raw); +		} +	} +  	return afc;  } @@ -303,11 +340,53 @@ int ifuse_truncate(const char *path, off_t size)  int ifuse_ftruncate(const char *path, off_t size, struct fuse_file_info *fi)  {  	iphone_afc_client_t afc = fuse_get_context()->private_data; -	iphone_afc_file_t file = g_hash_table_lookup(file_handles, &fi->fh); -	if (!file) -		return -ENOENT; -	return iphone_afc_truncate_file(afc, file, size); +	return iphone_afc_truncate_file(afc, fi->fh, size); +} + +int ifuse_readlink(const char *path, char *linktarget, size_t buflen) +{ +	int i, ret; +	char **info = NULL; +	if (!path || !linktarget || (buflen == 0)) { +		return -EINVAL; +	} +	linktarget[0] = '\0'; // in case the link target cannot be determined +	iphone_afc_client_t afc = fuse_get_context()->private_data; +	iphone_error_t res = iphone_afc_get_file_info(afc, path, &info); +	if ((res == IPHONE_E_SUCCESS) && info) { +		ret = -1; +		for (i = 0; info[i]; i+=2) { +			if (!strcmp(info[i], "LinkTarget")) { +				strncpy(linktarget, info[i+1], buflen-1); +				linktarget[buflen-1] = '\0'; +				ret = 0; +			} +		} +		free_dictionary(info); +	} else { +		ret = -1; +	} +	 +	return ret; +} + +int ifuse_symlink(const char *target, const char *linkname) +{ +	iphone_afc_client_t afc = fuse_get_context()->private_data; +	if (IPHONE_E_SUCCESS == iphone_afc_make_link(afc, IPHONE_AFC_SYMLINK, target, linkname)) +		return 0; +	else +		return -1;  +} + +int ifuse_link(const char *target, const char *linkname) +{ +	iphone_afc_client_t afc = fuse_get_context()->private_data; +	if (IPHONE_E_SUCCESS == iphone_afc_make_link(afc, IPHONE_AFC_HARDLINK, target, linkname)) +		return 0; +	else +		return -1;   }  int ifuse_unlink(const char *path) @@ -360,6 +439,9 @@ static struct fuse_operations ifuse_oper = {  	.write = ifuse_write,  	.truncate = ifuse_truncate,  	.ftruncate = ifuse_ftruncate, +	.readlink = ifuse_readlink, +	.symlink = ifuse_symlink, +	.link = ifuse_link,  	.unlink = ifuse_unlink,  	.rename = ifuse_rename,  	.fsync = ifuse_fsync, | 
