xref: /minix3/minix/lib/libvboxfs/file.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc /* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
2*433d6423SLionel Sambuc 
3*433d6423SLionel Sambuc #include "inc.h"
4*433d6423SLionel Sambuc 
5*433d6423SLionel Sambuc /*
6*433d6423SLionel Sambuc  * We perform all file I/O using a local, intermediate buffer.  While in theory
7*433d6423SLionel Sambuc  * it would be possible to perform direct DMA from/to the user process, this
8*433d6423SLionel Sambuc  * does not work in practice: on short reads, VirtualBox copies back the entire
9*433d6423SLionel Sambuc  * provided buffer rather than only the part actually filled, resulting in the
10*433d6423SLionel Sambuc  * unused part of the buffer being clobbered.  Marking the buffer as bi-
11*433d6423SLionel Sambuc  * directional would solve this, except it would also eliminate all the
12*433d6423SLionel Sambuc  * zero-copy benefits for reads; in addition, it is prevented by the protection
13*433d6423SLionel Sambuc  * set on the given grant.
14*433d6423SLionel Sambuc  */
15*433d6423SLionel Sambuc 
16*433d6423SLionel Sambuc #define VBOXFS_MAX_FILEIO	65536	/* maximum I/O chunk size */
17*433d6423SLionel Sambuc 
18*433d6423SLionel Sambuc static char iobuf[VBOXFS_MAX_FILEIO];
19*433d6423SLionel Sambuc 
20*433d6423SLionel Sambuc /*
21*433d6423SLionel Sambuc  * Open a file.
22*433d6423SLionel Sambuc  */
23*433d6423SLionel Sambuc int
24*433d6423SLionel Sambuc vboxfs_open(char *path, int flags, int mode, sffs_file_t *handle)
25*433d6423SLionel Sambuc {
26*433d6423SLionel Sambuc 	vboxfs_handle_t *handlep;
27*433d6423SLionel Sambuc 	int r;
28*433d6423SLionel Sambuc 
29*433d6423SLionel Sambuc 	handlep = (vboxfs_handle_t *) malloc(sizeof(*handlep));
30*433d6423SLionel Sambuc 
31*433d6423SLionel Sambuc 	if ((r = vboxfs_open_file(path, flags, mode, handlep, NULL)) != OK) {
32*433d6423SLionel Sambuc 		free(handlep);
33*433d6423SLionel Sambuc 
34*433d6423SLionel Sambuc 		return r;
35*433d6423SLionel Sambuc 	}
36*433d6423SLionel Sambuc 
37*433d6423SLionel Sambuc 	*handle = (sffs_file_t) handlep;
38*433d6423SLionel Sambuc 
39*433d6423SLionel Sambuc 	return OK;
40*433d6423SLionel Sambuc }
41*433d6423SLionel Sambuc 
42*433d6423SLionel Sambuc /*
43*433d6423SLionel Sambuc  * Read or write a chunk from or to a file.
44*433d6423SLionel Sambuc  */
45*433d6423SLionel Sambuc static ssize_t
46*433d6423SLionel Sambuc read_write(vboxfs_handle_t handle, char *buf, size_t size, u64_t pos,
47*433d6423SLionel Sambuc 	int write)
48*433d6423SLionel Sambuc {
49*433d6423SLionel Sambuc 	vbox_param_t param[5];
50*433d6423SLionel Sambuc 	int r, dir, call;
51*433d6423SLionel Sambuc 
52*433d6423SLionel Sambuc 	dir = write ? VBOX_DIR_OUT : VBOX_DIR_IN;
53*433d6423SLionel Sambuc 	call = write ? VBOXFS_CALL_WRITE : VBOXFS_CALL_READ;
54*433d6423SLionel Sambuc 
55*433d6423SLionel Sambuc 	vbox_set_u32(&param[0], vboxfs_root);
56*433d6423SLionel Sambuc 	vbox_set_u64(&param[1], handle);
57*433d6423SLionel Sambuc 	vbox_set_u64(&param[2], pos);
58*433d6423SLionel Sambuc 	vbox_set_u32(&param[3], size);
59*433d6423SLionel Sambuc 	vbox_set_ptr(&param[4], buf, size, dir);
60*433d6423SLionel Sambuc 
61*433d6423SLionel Sambuc 	if ((r = vbox_call(vboxfs_conn, call, param, 5, NULL)) != OK)
62*433d6423SLionel Sambuc 		return r;
63*433d6423SLionel Sambuc 
64*433d6423SLionel Sambuc 	return vbox_get_u32(&param[3]);
65*433d6423SLionel Sambuc }
66*433d6423SLionel Sambuc 
67*433d6423SLionel Sambuc /*
68*433d6423SLionel Sambuc  * Read from a file.
69*433d6423SLionel Sambuc  */
70*433d6423SLionel Sambuc ssize_t
71*433d6423SLionel Sambuc vboxfs_read(sffs_file_t handle, char *buf, size_t size, u64_t pos)
72*433d6423SLionel Sambuc {
73*433d6423SLionel Sambuc 	vboxfs_handle_t *handlep;
74*433d6423SLionel Sambuc 
75*433d6423SLionel Sambuc 	handlep = (vboxfs_handle_t *) handle;
76*433d6423SLionel Sambuc 
77*433d6423SLionel Sambuc 	return read_write(*handlep, buf, size, pos, FALSE /*write*/);
78*433d6423SLionel Sambuc }
79*433d6423SLionel Sambuc 
80*433d6423SLionel Sambuc /*
81*433d6423SLionel Sambuc  * Write to a file.
82*433d6423SLionel Sambuc  */
83*433d6423SLionel Sambuc ssize_t
84*433d6423SLionel Sambuc vboxfs_write(sffs_file_t handle, char *buf, size_t len, u64_t pos)
85*433d6423SLionel Sambuc {
86*433d6423SLionel Sambuc 	vboxfs_handle_t *handlep;
87*433d6423SLionel Sambuc 
88*433d6423SLionel Sambuc 	handlep = (vboxfs_handle_t *) handle;
89*433d6423SLionel Sambuc 
90*433d6423SLionel Sambuc 	return read_write(*handlep, buf, len, pos, TRUE /*write*/);
91*433d6423SLionel Sambuc }
92*433d6423SLionel Sambuc 
93*433d6423SLionel Sambuc /*
94*433d6423SLionel Sambuc  * Close a file handle.
95*433d6423SLionel Sambuc  */
96*433d6423SLionel Sambuc int
97*433d6423SLionel Sambuc vboxfs_close(sffs_file_t handle)
98*433d6423SLionel Sambuc {
99*433d6423SLionel Sambuc 	vboxfs_handle_t *handlep;
100*433d6423SLionel Sambuc 
101*433d6423SLionel Sambuc 	handlep = (vboxfs_handle_t *) handle;
102*433d6423SLionel Sambuc 
103*433d6423SLionel Sambuc 	vboxfs_close_file(*handlep);
104*433d6423SLionel Sambuc 
105*433d6423SLionel Sambuc 	free(handlep);
106*433d6423SLionel Sambuc 
107*433d6423SLionel Sambuc 	return OK;
108*433d6423SLionel Sambuc }
109*433d6423SLionel Sambuc 
110*433d6423SLionel Sambuc /*
111*433d6423SLionel Sambuc  * Return an internal buffer address and size for I/O operations.
112*433d6423SLionel Sambuc  */
113*433d6423SLionel Sambuc size_t
114*433d6423SLionel Sambuc vboxfs_buffer(char **ptr)
115*433d6423SLionel Sambuc {
116*433d6423SLionel Sambuc 
117*433d6423SLionel Sambuc 	*ptr = iobuf;
118*433d6423SLionel Sambuc 	return sizeof(iobuf);
119*433d6423SLionel Sambuc }
120