xref: /minix3/minix/lib/libvboxfs/file.c (revision 94e65446c4f963450ea94b8becc02cec062675cd)
1433d6423SLionel Sambuc /* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
2433d6423SLionel Sambuc 
3433d6423SLionel Sambuc #include "inc.h"
4433d6423SLionel Sambuc 
5433d6423SLionel Sambuc /*
6433d6423SLionel Sambuc  * We perform all file I/O using a local, intermediate buffer.  While in theory
7433d6423SLionel Sambuc  * it would be possible to perform direct DMA from/to the user process, this
8433d6423SLionel Sambuc  * does not work in practice: on short reads, VirtualBox copies back the entire
9433d6423SLionel Sambuc  * provided buffer rather than only the part actually filled, resulting in the
10433d6423SLionel Sambuc  * unused part of the buffer being clobbered.  Marking the buffer as bi-
11433d6423SLionel Sambuc  * directional would solve this, except it would also eliminate all the
12433d6423SLionel Sambuc  * zero-copy benefits for reads; in addition, it is prevented by the protection
13433d6423SLionel Sambuc  * set on the given grant.
14433d6423SLionel Sambuc  */
15433d6423SLionel Sambuc 
16433d6423SLionel Sambuc #define VBOXFS_MAX_FILEIO	65536	/* maximum I/O chunk size */
17433d6423SLionel Sambuc 
18433d6423SLionel Sambuc static char iobuf[VBOXFS_MAX_FILEIO];
19433d6423SLionel Sambuc 
20433d6423SLionel Sambuc /*
21433d6423SLionel Sambuc  * Open a file.
22433d6423SLionel Sambuc  */
23433d6423SLionel Sambuc int
vboxfs_open(const char * path,int flags,int mode,sffs_file_t * handle)24*94e65446SDavid van Moolenbroek vboxfs_open(const char *path, int flags, int mode, sffs_file_t *handle)
25433d6423SLionel Sambuc {
26433d6423SLionel Sambuc 	vboxfs_handle_t *handlep;
27433d6423SLionel Sambuc 	int r;
28433d6423SLionel Sambuc 
29433d6423SLionel Sambuc 	handlep = (vboxfs_handle_t *) malloc(sizeof(*handlep));
30433d6423SLionel Sambuc 
31433d6423SLionel Sambuc 	if ((r = vboxfs_open_file(path, flags, mode, handlep, NULL)) != OK) {
32433d6423SLionel Sambuc 		free(handlep);
33433d6423SLionel Sambuc 
34433d6423SLionel Sambuc 		return r;
35433d6423SLionel Sambuc 	}
36433d6423SLionel Sambuc 
37433d6423SLionel Sambuc 	*handle = (sffs_file_t) handlep;
38433d6423SLionel Sambuc 
39433d6423SLionel Sambuc 	return OK;
40433d6423SLionel Sambuc }
41433d6423SLionel Sambuc 
42433d6423SLionel Sambuc /*
43433d6423SLionel Sambuc  * Read or write a chunk from or to a file.
44433d6423SLionel Sambuc  */
45433d6423SLionel Sambuc static ssize_t
read_write(vboxfs_handle_t handle,char * buf,size_t size,u64_t pos,int write)46433d6423SLionel Sambuc read_write(vboxfs_handle_t handle, char *buf, size_t size, u64_t pos,
47433d6423SLionel Sambuc 	int write)
48433d6423SLionel Sambuc {
49433d6423SLionel Sambuc 	vbox_param_t param[5];
50433d6423SLionel Sambuc 	int r, dir, call;
51433d6423SLionel Sambuc 
52433d6423SLionel Sambuc 	dir = write ? VBOX_DIR_OUT : VBOX_DIR_IN;
53433d6423SLionel Sambuc 	call = write ? VBOXFS_CALL_WRITE : VBOXFS_CALL_READ;
54433d6423SLionel Sambuc 
55433d6423SLionel Sambuc 	vbox_set_u32(&param[0], vboxfs_root);
56433d6423SLionel Sambuc 	vbox_set_u64(&param[1], handle);
57433d6423SLionel Sambuc 	vbox_set_u64(&param[2], pos);
58433d6423SLionel Sambuc 	vbox_set_u32(&param[3], size);
59433d6423SLionel Sambuc 	vbox_set_ptr(&param[4], buf, size, dir);
60433d6423SLionel Sambuc 
61433d6423SLionel Sambuc 	if ((r = vbox_call(vboxfs_conn, call, param, 5, NULL)) != OK)
62433d6423SLionel Sambuc 		return r;
63433d6423SLionel Sambuc 
64433d6423SLionel Sambuc 	return vbox_get_u32(&param[3]);
65433d6423SLionel Sambuc }
66433d6423SLionel Sambuc 
67433d6423SLionel Sambuc /*
68433d6423SLionel Sambuc  * Read from a file.
69433d6423SLionel Sambuc  */
70433d6423SLionel Sambuc ssize_t
vboxfs_read(sffs_file_t handle,char * buf,size_t size,u64_t pos)71433d6423SLionel Sambuc vboxfs_read(sffs_file_t handle, char *buf, size_t size, u64_t pos)
72433d6423SLionel Sambuc {
73433d6423SLionel Sambuc 	vboxfs_handle_t *handlep;
74433d6423SLionel Sambuc 
75433d6423SLionel Sambuc 	handlep = (vboxfs_handle_t *) handle;
76433d6423SLionel Sambuc 
77433d6423SLionel Sambuc 	return read_write(*handlep, buf, size, pos, FALSE /*write*/);
78433d6423SLionel Sambuc }
79433d6423SLionel Sambuc 
80433d6423SLionel Sambuc /*
81433d6423SLionel Sambuc  * Write to a file.
82433d6423SLionel Sambuc  */
83433d6423SLionel Sambuc ssize_t
vboxfs_write(sffs_file_t handle,char * buf,size_t len,u64_t pos)84433d6423SLionel Sambuc vboxfs_write(sffs_file_t handle, char *buf, size_t len, u64_t pos)
85433d6423SLionel Sambuc {
86433d6423SLionel Sambuc 	vboxfs_handle_t *handlep;
87433d6423SLionel Sambuc 
88433d6423SLionel Sambuc 	handlep = (vboxfs_handle_t *) handle;
89433d6423SLionel Sambuc 
90433d6423SLionel Sambuc 	return read_write(*handlep, buf, len, pos, TRUE /*write*/);
91433d6423SLionel Sambuc }
92433d6423SLionel Sambuc 
93433d6423SLionel Sambuc /*
94433d6423SLionel Sambuc  * Close a file handle.
95433d6423SLionel Sambuc  */
96433d6423SLionel Sambuc int
vboxfs_close(sffs_file_t handle)97433d6423SLionel Sambuc vboxfs_close(sffs_file_t handle)
98433d6423SLionel Sambuc {
99433d6423SLionel Sambuc 	vboxfs_handle_t *handlep;
100433d6423SLionel Sambuc 
101433d6423SLionel Sambuc 	handlep = (vboxfs_handle_t *) handle;
102433d6423SLionel Sambuc 
103433d6423SLionel Sambuc 	vboxfs_close_file(*handlep);
104433d6423SLionel Sambuc 
105433d6423SLionel Sambuc 	free(handlep);
106433d6423SLionel Sambuc 
107433d6423SLionel Sambuc 	return OK;
108433d6423SLionel Sambuc }
109433d6423SLionel Sambuc 
110433d6423SLionel Sambuc /*
111433d6423SLionel Sambuc  * Return an internal buffer address and size for I/O operations.
112433d6423SLionel Sambuc  */
113433d6423SLionel Sambuc size_t
vboxfs_buffer(char ** ptr)114433d6423SLionel Sambuc vboxfs_buffer(char **ptr)
115433d6423SLionel Sambuc {
116433d6423SLionel Sambuc 
117433d6423SLionel Sambuc 	*ptr = iobuf;
118433d6423SLionel Sambuc 	return sizeof(iobuf);
119433d6423SLionel Sambuc }
120