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