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
vboxfs_open(const char * path,int flags,int mode,sffs_file_t * handle)24 vboxfs_open(const 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
read_write(vboxfs_handle_t handle,char * buf,size_t size,u64_t pos,int write)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(¶m[0], vboxfs_root);
56 vbox_set_u64(¶m[1], handle);
57 vbox_set_u64(¶m[2], pos);
58 vbox_set_u32(¶m[3], size);
59 vbox_set_ptr(¶m[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(¶m[3]);
65 }
66
67 /*
68 * Read from a file.
69 */
70 ssize_t
vboxfs_read(sffs_file_t handle,char * buf,size_t size,u64_t pos)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
vboxfs_write(sffs_file_t handle,char * buf,size_t len,u64_t pos)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
vboxfs_close(sffs_file_t handle)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
vboxfs_buffer(char ** ptr)114 vboxfs_buffer(char **ptr)
115 {
116
117 *ptr = iobuf;
118 return sizeof(iobuf);
119 }
120