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(¶m[0], vboxfs_root);
56433d6423SLionel Sambuc vbox_set_u64(¶m[1], handle);
57433d6423SLionel Sambuc vbox_set_u64(¶m[2], pos);
58433d6423SLionel Sambuc vbox_set_u32(¶m[3], size);
59433d6423SLionel Sambuc vbox_set_ptr(¶m[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(¶m[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