120 lines
2.4 KiB
C
120 lines
2.4 KiB
C
/* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
|
|
|
|
#include "inc.h"
|
|
|
|
/*
|
|
* We perform all file I/O using a local, intermediate buffer. While in theory
|
|
* it would be possible to perform direct DMA from/to the user process, this
|
|
* does not work in practice: on short reads, VirtualBox copies back the entire
|
|
* provided buffer rather than only the part actually filled, resulting in the
|
|
* unused part of the buffer being clobbered. Marking the buffer as bi-
|
|
* directional would solve this, except it would also eliminate all the
|
|
* zero-copy benefits for reads; in addition, it is prevented by the protection
|
|
* set on the given grant.
|
|
*/
|
|
|
|
#define VBOXFS_MAX_FILEIO 65536 /* maximum I/O chunk size */
|
|
|
|
static char iobuf[VBOXFS_MAX_FILEIO];
|
|
|
|
/*
|
|
* Open a file.
|
|
*/
|
|
int
|
|
vboxfs_open(char *path, int flags, int mode, sffs_file_t *handle)
|
|
{
|
|
vboxfs_handle_t *handlep;
|
|
int r;
|
|
|
|
handlep = (vboxfs_handle_t *) malloc(sizeof(*handlep));
|
|
|
|
if ((r = vboxfs_open_file(path, flags, mode, handlep, NULL)) != OK) {
|
|
free(handlep);
|
|
|
|
return r;
|
|
}
|
|
|
|
*handle = (sffs_file_t) handlep;
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*
|
|
* Read or write a chunk from or to a file.
|
|
*/
|
|
static ssize_t
|
|
read_write(vboxfs_handle_t handle, char *buf, size_t size, u64_t pos,
|
|
int write)
|
|
{
|
|
vbox_param_t param[5];
|
|
int r, dir, call;
|
|
|
|
dir = write ? VBOX_DIR_OUT : VBOX_DIR_IN;
|
|
call = write ? VBOXFS_CALL_WRITE : VBOXFS_CALL_READ;
|
|
|
|
vbox_set_u32(¶m[0], vboxfs_root);
|
|
vbox_set_u64(¶m[1], handle);
|
|
vbox_set_u64(¶m[2], pos);
|
|
vbox_set_u32(¶m[3], size);
|
|
vbox_set_ptr(¶m[4], buf, size, dir);
|
|
|
|
if ((r = vbox_call(vboxfs_conn, call, param, 5, NULL)) != OK)
|
|
return r;
|
|
|
|
return vbox_get_u32(¶m[3]);
|
|
}
|
|
|
|
/*
|
|
* Read from a file.
|
|
*/
|
|
ssize_t
|
|
vboxfs_read(sffs_file_t handle, char *buf, size_t size, u64_t pos)
|
|
{
|
|
vboxfs_handle_t *handlep;
|
|
|
|
handlep = (vboxfs_handle_t *) handle;
|
|
|
|
return read_write(*handlep, buf, size, pos, FALSE /*write*/);
|
|
}
|
|
|
|
/*
|
|
* Write to a file.
|
|
*/
|
|
ssize_t
|
|
vboxfs_write(sffs_file_t handle, char *buf, size_t len, u64_t pos)
|
|
{
|
|
vboxfs_handle_t *handlep;
|
|
|
|
handlep = (vboxfs_handle_t *) handle;
|
|
|
|
return read_write(*handlep, buf, len, pos, TRUE /*write*/);
|
|
}
|
|
|
|
/*
|
|
* Close a file handle.
|
|
*/
|
|
int
|
|
vboxfs_close(sffs_file_t handle)
|
|
{
|
|
vboxfs_handle_t *handlep;
|
|
|
|
handlep = (vboxfs_handle_t *) handle;
|
|
|
|
vboxfs_close_file(*handlep);
|
|
|
|
free(handlep);
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*
|
|
* Return an internal buffer address and size for I/O operations.
|
|
*/
|
|
size_t
|
|
vboxfs_buffer(char **ptr)
|
|
{
|
|
|
|
*ptr = iobuf;
|
|
return sizeof(iobuf);
|
|
}
|