Add libvboxfs: VirtualBox shared folders library
This commit is contained in:
parent
ef7b484e5c
commit
bb4d055fa6
17 changed files with 1212 additions and 3 deletions
|
@ -18,7 +18,7 @@ INCS+= minix/acpi.h minix/audio_fw.h minix/bitmap.h \
|
|||
minix/sound.h minix/spin.h minix/sys_config.h minix/sysinfo.h \
|
||||
minix/syslib.h minix/sysutil.h minix/timers.h minix/type.h \
|
||||
minix/tty.h minix/u64.h minix/usb.h minix/usb_ch9.h minix/vbox.h \
|
||||
minix/vboxif.h minix/vboxtype.h minix/vm.h \
|
||||
minix/vboxfs.h minix/vboxif.h minix/vboxtype.h minix/vm.h \
|
||||
minix/vfsif.h minix/vtreefs.h minix/libminixfs.h minix/netsock.h
|
||||
|
||||
INCS+= net/gen/arp_io.h net/gen/dhcp.h net/gen/ether.h \
|
||||
|
|
12
include/minix/vboxfs.h
Normal file
12
include/minix/vboxfs.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
|
||||
|
||||
#ifndef _MINIX_VBOXFS_H
|
||||
#define _MINIX_VBOXFS_H
|
||||
|
||||
#include <minix/sffs.h>
|
||||
|
||||
int vboxfs_init(char *share, const struct sffs_table **tablep,
|
||||
int *case_insens, int *read_only);
|
||||
void vboxfs_cleanup(void);
|
||||
|
||||
#endif /* _MINIX_VBOXFS_H */
|
|
@ -6,7 +6,7 @@ SUBDIR= csu libcompat_minix libc libblockdriver libchardriver \
|
|||
libexec libdevman libusb libminlib libasyn \
|
||||
libddekit libminixfs libbdev libelf libminc libcrypt libterminfo \
|
||||
libcurses libvassert libutil libpuffs librefuse libbz2 libarchive \
|
||||
libprop libnetsock libsffs libhgfs
|
||||
libprop libnetsock libsffs libhgfs libvboxfs
|
||||
|
||||
SUBDIR+= ../external/public-domain/xz/lib
|
||||
|
||||
|
|
8
lib/libvboxfs/Makefile
Normal file
8
lib/libvboxfs/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Makefile for libvboxfs
|
||||
.include <bsd.own.mk>
|
||||
|
||||
LIB= vboxfs
|
||||
|
||||
SRCS= attr.c dir.c file.c handle.c info.c link.c path.c vboxfs.c
|
||||
|
||||
.include <bsd.lib.mk>
|
169
lib/libvboxfs/attr.c
Normal file
169
lib/libvboxfs/attr.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
/* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
|
||||
|
||||
#include "inc.h"
|
||||
|
||||
/*
|
||||
* Convert a VirtualBox timestamp to a POSIX timespec structure.
|
||||
* VirtualBox' timestamps are in nanoseconds since the UNIX epoch.
|
||||
*/
|
||||
static void
|
||||
get_time(struct timespec *tsp, u64_t nsecs)
|
||||
{
|
||||
|
||||
tsp->tv_sec = div64u(nsecs, 1000000000);
|
||||
tsp->tv_nsec = rem64u(nsecs, 1000000000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a POSIX timespec structure to a VirtualBox timestamp.
|
||||
*/
|
||||
static u64_t
|
||||
set_time(struct timespec *tsp)
|
||||
{
|
||||
|
||||
return add64u(mul64u(tsp->tv_sec, 1000000000), tsp->tv_nsec);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the given attribute structure with VirtualBox object information.
|
||||
*/
|
||||
void
|
||||
vboxfs_get_attr(struct sffs_attr *attr, vboxfs_objinfo_t *info)
|
||||
{
|
||||
|
||||
if (attr->a_mask & SFFS_ATTR_SIZE)
|
||||
attr->a_size = info->size;
|
||||
if (attr->a_mask & SFFS_ATTR_MODE)
|
||||
attr->a_mode = VBOXFS_GET_MODE(info->attr.mode);
|
||||
if (attr->a_mask & SFFS_ATTR_ATIME)
|
||||
get_time(&attr->a_atime, info->atime);
|
||||
if (attr->a_mask & SFFS_ATTR_MTIME)
|
||||
get_time(&attr->a_mtime, info->mtime);
|
||||
if (attr->a_mask & SFFS_ATTR_CTIME)
|
||||
get_time(&attr->a_ctime, info->ctime);
|
||||
if (attr->a_mask & SFFS_ATTR_CRTIME)
|
||||
get_time(&attr->a_crtime, info->crtime);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get file attributes.
|
||||
*/
|
||||
int
|
||||
vboxfs_getattr(char *path, struct sffs_attr *attr)
|
||||
{
|
||||
vbox_param_t param[3];
|
||||
vboxfs_path_t pathbuf;
|
||||
vboxfs_crinfo_t crinfo;
|
||||
int r;
|
||||
|
||||
if ((r = vboxfs_set_path(&pathbuf, path)) != OK)
|
||||
return r;
|
||||
|
||||
memset(&crinfo, 0, sizeof(crinfo));
|
||||
crinfo.flags = VBOXFS_CRFLAG_LOOKUP;
|
||||
/* crinfo.info.attr.add is not checked */
|
||||
|
||||
vbox_set_u32(¶m[0], vboxfs_root);
|
||||
vbox_set_ptr(¶m[1], &pathbuf, vboxfs_get_path_size(&pathbuf),
|
||||
VBOX_DIR_OUT);
|
||||
vbox_set_ptr(¶m[2], &crinfo, sizeof(crinfo), VBOX_DIR_INOUT);
|
||||
|
||||
r = vbox_call(vboxfs_conn, VBOXFS_CALL_CREATE, param, 3, NULL);
|
||||
if (r != OK)
|
||||
return r;
|
||||
|
||||
switch (crinfo.result) {
|
||||
case VBOXFS_PATH_NOT_FOUND:
|
||||
/* This could also be ENOTDIR. See note in handle.c. */
|
||||
case VBOXFS_FILE_NOT_FOUND:
|
||||
return ENOENT;
|
||||
case VBOXFS_FILE_EXISTS:
|
||||
break; /* success */
|
||||
default:
|
||||
return EIO; /* should never happen */
|
||||
}
|
||||
|
||||
vboxfs_get_attr(attr, &crinfo.info);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set file size.
|
||||
*/
|
||||
static int
|
||||
set_size(char *path, u64_t size)
|
||||
{
|
||||
vboxfs_objinfo_t info;
|
||||
vboxfs_handle_t h;
|
||||
int r;
|
||||
|
||||
if ((r = vboxfs_open_file(path, O_WRONLY, S_IFREG, &h, NULL)) != OK)
|
||||
return r;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.size = size;
|
||||
|
||||
r = vboxfs_getset_info(h, VBOXFS_INFO_SET | VBOXFS_INFO_SIZE, &info,
|
||||
sizeof(info));
|
||||
|
||||
vboxfs_close_file(h);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set file attributes.
|
||||
*/
|
||||
int
|
||||
vboxfs_setattr(char *path, struct sffs_attr *attr)
|
||||
{
|
||||
vboxfs_objinfo_t info;
|
||||
vboxfs_handle_t h;
|
||||
int r;
|
||||
|
||||
/*
|
||||
* Setting the size of a path cannot be combined with other attribute
|
||||
* modifications, because we cannot fail atomically.
|
||||
*/
|
||||
if (attr->a_mask & SFFS_ATTR_SIZE) {
|
||||
assert(attr->a_mask == SFFS_ATTR_SIZE);
|
||||
|
||||
return set_size(path, attr->a_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* By passing a pointer to an object information structure, we open the
|
||||
* file for attribute manipulation. Note that this call will open the
|
||||
* file as a regular file. This works on directories as well.
|
||||
*/
|
||||
if ((r = vboxfs_open_file(path, O_WRONLY, 0, &h, &info)) != OK)
|
||||
return r;
|
||||
|
||||
info.attr.add = VBOXFS_OBJATTR_ADD_NONE;
|
||||
|
||||
/* Update the file's permissions if requested. */
|
||||
if (attr->a_mask & SFFS_ATTR_MODE)
|
||||
info.attr.mode =
|
||||
VBOXFS_SET_MODE(info.attr.mode & S_IFMT, attr->a_mode);
|
||||
|
||||
/*
|
||||
* Update various file times if requested. Not all changes may
|
||||
* be honered. A zero time indicates no change.
|
||||
*/
|
||||
info.atime = (attr->a_mask & SFFS_ATTR_ATIME) ?
|
||||
set_time(&attr->a_atime) : 0;
|
||||
info.mtime = (attr->a_mask & SFFS_ATTR_MTIME) ?
|
||||
set_time(&attr->a_ctime) : 0;
|
||||
info.ctime = (attr->a_mask & SFFS_ATTR_CTIME) ?
|
||||
set_time(&attr->a_ctime) : 0;
|
||||
info.crtime = (attr->a_mask & SFFS_ATTR_CRTIME) ?
|
||||
set_time(&attr->a_crtime) : 0;
|
||||
|
||||
r = vboxfs_getset_info(h, VBOXFS_INFO_SET | VBOXFS_INFO_FILE, &info,
|
||||
sizeof(info));
|
||||
|
||||
vboxfs_close_file(h);
|
||||
|
||||
return r;
|
||||
}
|
245
lib/libvboxfs/dir.c
Normal file
245
lib/libvboxfs/dir.c
Normal file
|
@ -0,0 +1,245 @@
|
|||
/* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
|
||||
|
||||
#include "inc.h"
|
||||
|
||||
/*
|
||||
* Directories will generally be accessed sequentially, but there is no
|
||||
* guarantee that this is actually the case. In particular, multiple user
|
||||
* processes may iterate over the same directory concurrently, and since
|
||||
* process information is lost in the VFS/FS protocol, the result is a
|
||||
* nonsequential pattern on the same single directory handle. Therefore, we
|
||||
* must support random access. Since the VirtualBox shared folders interface
|
||||
* does not allow for random access (the resume point cannot be used for this),
|
||||
* we choose to read in the contents of the directory upon open, and cache it
|
||||
* until the directory is closed again. The risk is that the cached contents
|
||||
* will go stale.
|
||||
*
|
||||
* The directory will always be closed once one reader finishes going through
|
||||
* the entire directory, so the problem is rather limited anyway. Ideally, the
|
||||
* directory contents would be refreshed upon any invalidating local action as
|
||||
* well as after a certain time span (since the file system can be changed from
|
||||
* the host as well). This is currently not implemented, because the odds of
|
||||
* things going wrong are pretty small, and the effects are not devastating.
|
||||
*
|
||||
* The calling functions may also request the same directory entry twice in a
|
||||
* row, because the entry does not fit in the user buffer the first time. The
|
||||
* routines here optimize for repeat-sequential access, while supporting fully
|
||||
* random access as well.
|
||||
*/
|
||||
|
||||
#define VBOXFS_DIRDATA_SIZE 8192 /* data allocation granularity */
|
||||
|
||||
typedef struct vboxfs_dirblock_s {
|
||||
STAILQ_ENTRY(vboxfs_dirblock_s) next;
|
||||
unsigned int count;
|
||||
char data[VBOXFS_DIRDATA_SIZE];
|
||||
} vboxfs_dirblock_t;
|
||||
|
||||
typedef struct {
|
||||
STAILQ_HEAD(blocks, vboxfs_dirblock_s) blocks;
|
||||
unsigned int index;
|
||||
vboxfs_dirblock_t *block;
|
||||
unsigned int bindex;
|
||||
unsigned int bpos;
|
||||
} vboxfs_dirdata_t;
|
||||
|
||||
/*
|
||||
* Free the memory allocated for the given directory contents storage.
|
||||
*/
|
||||
static void
|
||||
free_dir(vboxfs_dirdata_t *dirdata)
|
||||
{
|
||||
vboxfs_dirblock_t *block;
|
||||
|
||||
while (!STAILQ_EMPTY(&dirdata->blocks)) {
|
||||
block = STAILQ_FIRST(&dirdata->blocks);
|
||||
|
||||
STAILQ_REMOVE_HEAD(&dirdata->blocks, next);
|
||||
|
||||
free(block);
|
||||
}
|
||||
|
||||
free(dirdata);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read all the contents of the given directory, allocating memory as needed to
|
||||
* store the data.
|
||||
*/
|
||||
static int
|
||||
read_dir(vboxfs_handle_t handle, sffs_dir_t *dirp)
|
||||
{
|
||||
vboxfs_dirdata_t *dirdata;
|
||||
vboxfs_dirblock_t *block;
|
||||
vbox_param_t param[8];
|
||||
unsigned int count;
|
||||
int r;
|
||||
|
||||
dirdata = (vboxfs_dirdata_t *) malloc(sizeof(vboxfs_dirdata_t));
|
||||
if (dirdata == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
memset(dirdata, 0, sizeof(*dirdata));
|
||||
STAILQ_INIT(&dirdata->blocks);
|
||||
|
||||
r = OK;
|
||||
|
||||
do {
|
||||
block =
|
||||
(vboxfs_dirblock_t *) malloc(sizeof(vboxfs_dirblock_t));
|
||||
if (block == NULL) {
|
||||
r = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
vbox_set_u32(¶m[0], vboxfs_root);
|
||||
vbox_set_u64(¶m[1], handle);
|
||||
vbox_set_u32(¶m[2], 0); /* flags */
|
||||
vbox_set_u32(¶m[3], sizeof(block->data));
|
||||
vbox_set_ptr(¶m[4], NULL, 0, VBOX_DIR_OUT);
|
||||
vbox_set_ptr(¶m[5], block->data, sizeof(block->data),
|
||||
VBOX_DIR_IN);
|
||||
vbox_set_u32(¶m[6], 0); /* resume point */
|
||||
vbox_set_u32(¶m[7], 0); /* number of files */
|
||||
|
||||
/* If the call fails, stop. */
|
||||
if ((r = vbox_call(vboxfs_conn, VBOXFS_CALL_LIST, param, 8,
|
||||
NULL)) != OK) {
|
||||
free(block);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the number of returned files is zero, stop. */
|
||||
if ((count = vbox_get_u32(¶m[7])) == 0) {
|
||||
free(block);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the block to the list. We could realloc() the block to
|
||||
* free unused tail space, but this is not likely to gain us
|
||||
* much in general.
|
||||
*/
|
||||
block->count = count;
|
||||
STAILQ_INSERT_TAIL(&dirdata->blocks, block, next);
|
||||
|
||||
/* Continue until a zero resume point is returned. */
|
||||
} while (vbox_get_u32(¶m[6]) != 0);
|
||||
|
||||
if (r != OK) {
|
||||
free_dir(dirdata);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
dirdata->block = STAILQ_FIRST(&dirdata->blocks);
|
||||
|
||||
*dirp = (sffs_dir_t) dirdata;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a directory.
|
||||
*/
|
||||
int
|
||||
vboxfs_opendir(char *path, sffs_dir_t *handle)
|
||||
{
|
||||
vboxfs_handle_t h;
|
||||
int r;
|
||||
|
||||
/* Open the directory. */
|
||||
if ((r = vboxfs_open_file(path, O_RDONLY, S_IFDIR, &h, NULL)) != OK)
|
||||
return r;
|
||||
|
||||
/*
|
||||
* Upon success, read in the full contents of the directory right away.
|
||||
* If it succeeds, this will also set the caller's directory handle.
|
||||
*/
|
||||
r = read_dir(h, handle);
|
||||
|
||||
/* We do not need the directory to be open anymore now. */
|
||||
vboxfs_close_file(h);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read one entry from a directory. On success, copy the name into buf, and
|
||||
* return the requested attributes. If the name (including terminating null)
|
||||
* exceeds size, return ENAMETOOLONG. Do not return dot and dot-dot entries.
|
||||
* Return ENOENT if the index exceeds the number of files.
|
||||
*/
|
||||
int
|
||||
vboxfs_readdir(sffs_dir_t handle, unsigned int index, char *buf, size_t size,
|
||||
struct sffs_attr *attr)
|
||||
{
|
||||
vboxfs_dirdata_t *dirdata;
|
||||
vboxfs_dirinfo_t *dirinfo;
|
||||
int r;
|
||||
|
||||
dirdata = (vboxfs_dirdata_t *) handle;
|
||||
|
||||
/*
|
||||
* If the saved index exceeds the requested index, start from the
|
||||
* beginning.
|
||||
*/
|
||||
if (dirdata->index > index) {
|
||||
dirdata->index = 0;
|
||||
dirdata->bindex = 0;
|
||||
dirdata->bpos = 0;
|
||||
dirdata->block = STAILQ_FIRST(&dirdata->blocks);
|
||||
}
|
||||
|
||||
/* Loop until we find the requested entry or we run out of entries. */
|
||||
while (dirdata->block != NULL) {
|
||||
dirinfo =
|
||||
(vboxfs_dirinfo_t *) &dirdata->block->data[dirdata->bpos];
|
||||
|
||||
/* Consider all entries that are not dot or dot-dot. */
|
||||
if (dirinfo->name.len > 2 || dirinfo->name.data[0] != '.' ||
|
||||
(dirinfo->name.len == 2 && dirinfo->name.data[1] != '.')) {
|
||||
|
||||
if (dirdata->index == index)
|
||||
break;
|
||||
|
||||
dirdata->index++;
|
||||
}
|
||||
|
||||
/* Advance to the next entry. */
|
||||
dirdata->bpos += offsetof(vboxfs_dirinfo_t, name) +
|
||||
offsetof(vboxfs_path_t, data) + dirinfo->name.size;
|
||||
if (++dirdata->bindex >= dirdata->block->count) {
|
||||
dirdata->block = STAILQ_NEXT(dirdata->block, next);
|
||||
dirdata->bindex = 0;
|
||||
dirdata->bpos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not enough files to satisfy the request? */
|
||||
if (dirdata->block == NULL)
|
||||
return ENOENT;
|
||||
|
||||
/* Return the information for the file we found. */
|
||||
if ((r = vboxfs_get_path(&dirinfo->name, buf, size)) != OK)
|
||||
return r;
|
||||
|
||||
vboxfs_get_attr(attr, &dirinfo->info);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close a directory.
|
||||
*/
|
||||
int
|
||||
vboxfs_closedir(sffs_dir_t handle)
|
||||
{
|
||||
vboxfs_dirdata_t *dirdata;
|
||||
|
||||
dirdata = (vboxfs_dirdata_t *) handle;
|
||||
|
||||
free_dir(dirdata);
|
||||
|
||||
return OK;
|
||||
}
|
119
lib/libvboxfs/file.c
Normal file
119
lib/libvboxfs/file.c
Normal file
|
@ -0,0 +1,119 @@
|
|||
/* 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);
|
||||
}
|
9
lib/libvboxfs/glo.h
Normal file
9
lib/libvboxfs/glo.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
|
||||
|
||||
#ifndef _VBOXFS_GLO_H
|
||||
#define _VBOXFS_GLO_H
|
||||
|
||||
extern vbox_conn_t vboxfs_conn;
|
||||
extern vboxfs_root_t vboxfs_root;
|
||||
|
||||
#endif /* !_VBOXFS_GLO_H */
|
121
lib/libvboxfs/handle.c
Normal file
121
lib/libvboxfs/handle.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
/* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
|
||||
|
||||
#include "inc.h"
|
||||
|
||||
/*
|
||||
* Create or open a file or directory.
|
||||
*/
|
||||
int
|
||||
vboxfs_open_file(char *path, int flags, int mode, vboxfs_handle_t *handlep,
|
||||
vboxfs_objinfo_t *infop)
|
||||
{
|
||||
vbox_param_t param[3];
|
||||
vboxfs_path_t pathbuf;
|
||||
vboxfs_crinfo_t crinfo;
|
||||
int r, dir, rflag, wflag;
|
||||
|
||||
if ((r = vboxfs_set_path(&pathbuf, path)) != OK)
|
||||
return r;
|
||||
|
||||
memset(&crinfo, 0, sizeof(crinfo));
|
||||
|
||||
/*
|
||||
* Note that the mode may not be set at all. If no new file may be
|
||||
* created, this is not a problem. The following test succeeds only if
|
||||
* the caller explicitly specified that a directory is involved.
|
||||
*/
|
||||
dir = S_ISDIR(mode);
|
||||
|
||||
/* Convert open(2) flags to VirtualBox creation flags. */
|
||||
if (flags & O_APPEND)
|
||||
return EINVAL; /* not supported at this time */
|
||||
|
||||
if (flags & O_CREAT) {
|
||||
crinfo.flags = VBOXFS_CRFLAG_CREATE_IF_NEW;
|
||||
|
||||
if (flags & O_EXCL)
|
||||
crinfo.flags |= VBOXFS_CRFLAG_FAIL_IF_EXISTS;
|
||||
else if (flags & O_TRUNC)
|
||||
crinfo.flags |= VBOXFS_CRFLAG_TRUNC_IF_EXISTS;
|
||||
else
|
||||
crinfo.flags |= VBOXFS_CRFLAG_OPEN_IF_EXISTS;
|
||||
} else {
|
||||
crinfo.flags = VBOXFS_CRFLAG_FAIL_IF_NEW;
|
||||
|
||||
if (flags & O_TRUNC)
|
||||
crinfo.flags |= VBOXFS_CRFLAG_TRUNC_IF_EXISTS;
|
||||
else
|
||||
crinfo.flags |= VBOXFS_CRFLAG_OPEN_IF_EXISTS;
|
||||
}
|
||||
|
||||
/*
|
||||
* If an object information structure is given, open the file only to
|
||||
* retrieve or change its attributes.
|
||||
*/
|
||||
if (infop != NULL) {
|
||||
rflag = VBOXFS_CRFLAG_READ_ATTR;
|
||||
wflag = VBOXFS_CRFLAG_WRITE_ATTR;
|
||||
} else {
|
||||
rflag = VBOXFS_CRFLAG_READ;
|
||||
wflag = VBOXFS_CRFLAG_WRITE;
|
||||
}
|
||||
|
||||
switch (flags & O_ACCMODE) {
|
||||
case O_RDONLY: crinfo.flags |= rflag; break;
|
||||
case O_WRONLY: crinfo.flags |= wflag; break;
|
||||
case O_RDWR: crinfo.flags |= rflag | wflag; break;
|
||||
default: return EINVAL;
|
||||
}
|
||||
|
||||
if (S_ISDIR(mode))
|
||||
crinfo.flags |= VBOXFS_CRFLAG_DIRECTORY;
|
||||
|
||||
crinfo.info.attr.mode = VBOXFS_SET_MODE(dir ? S_IFDIR : S_IFREG, mode);
|
||||
crinfo.info.attr.add = VBOXFS_OBJATTR_ADD_NONE;
|
||||
|
||||
vbox_set_u32(¶m[0], vboxfs_root);
|
||||
vbox_set_ptr(¶m[1], &pathbuf, vboxfs_get_path_size(&pathbuf),
|
||||
VBOX_DIR_OUT);
|
||||
vbox_set_ptr(¶m[2], &crinfo, sizeof(crinfo), VBOX_DIR_INOUT);
|
||||
|
||||
r = vbox_call(vboxfs_conn, VBOXFS_CALL_CREATE, param, 3, NULL);
|
||||
if (r != OK)
|
||||
return r;
|
||||
|
||||
if (crinfo.handle == VBOXFS_INVALID_HANDLE) {
|
||||
switch (crinfo.result) {
|
||||
case VBOXFS_PATH_NOT_FOUND:
|
||||
/*
|
||||
* This could also mean ENOTDIR, but there does not
|
||||
* appear to be any way to distinguish that case.
|
||||
* Verifying with extra lookups seems overkill.
|
||||
*/
|
||||
case VBOXFS_FILE_NOT_FOUND:
|
||||
return ENOENT;
|
||||
case VBOXFS_FILE_EXISTS:
|
||||
return EEXIST;
|
||||
default:
|
||||
return EIO; /* should never happen */
|
||||
}
|
||||
}
|
||||
|
||||
*handlep = crinfo.handle;
|
||||
if (infop != NULL)
|
||||
*infop = crinfo.info;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close an open file handle.
|
||||
*/
|
||||
void
|
||||
vboxfs_close_file(vboxfs_handle_t handle)
|
||||
{
|
||||
vbox_param_t param[2];
|
||||
|
||||
vbox_set_u32(¶m[0], vboxfs_root);
|
||||
vbox_set_u64(¶m[1], handle);
|
||||
|
||||
/* Ignore errors here. We cannot do anything with them anyway. */
|
||||
(void) vbox_call(vboxfs_conn, VBOXFS_CALL_CLOSE, param, 2, NULL);
|
||||
}
|
18
lib/libvboxfs/inc.h
Normal file
18
lib/libvboxfs/inc.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
|
||||
|
||||
#ifndef _VBOXFS_INC_H
|
||||
#define _VBOXFS_INC_H
|
||||
|
||||
#include <minix/drivers.h>
|
||||
#include <minix/vbox.h>
|
||||
#include <minix/sffs.h>
|
||||
#include <minix/vboxfs.h>
|
||||
#include <sys/queue.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "vboxfs.h"
|
||||
#include "glo.h"
|
||||
#include "proto.h"
|
||||
|
||||
#endif /* !_VBOXFS_INC_H */
|
58
lib/libvboxfs/info.c
Normal file
58
lib/libvboxfs/info.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
|
||||
|
||||
#include "inc.h"
|
||||
|
||||
/*
|
||||
* Get or set file information.
|
||||
*/
|
||||
int
|
||||
vboxfs_getset_info(vboxfs_handle_t handle, u32_t flags, void *data,
|
||||
size_t size)
|
||||
{
|
||||
vbox_param_t param[5];
|
||||
|
||||
vbox_set_u32(¶m[0], vboxfs_root);
|
||||
vbox_set_u64(¶m[1], handle);
|
||||
vbox_set_u32(¶m[2], flags);
|
||||
vbox_set_u32(¶m[3], size);
|
||||
vbox_set_ptr(¶m[4], data, size, VBOX_DIR_INOUT);
|
||||
|
||||
return vbox_call(vboxfs_conn, VBOXFS_CALL_INFO, param, 5, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Query volume information.
|
||||
*/
|
||||
int
|
||||
vboxfs_query_vol(char *path, vboxfs_volinfo_t *volinfo)
|
||||
{
|
||||
vboxfs_handle_t h;
|
||||
int r;
|
||||
|
||||
if ((r = vboxfs_open_file(path, O_RDONLY, 0, &h, NULL)) != OK)
|
||||
return r;
|
||||
|
||||
r = vboxfs_getset_info(h, VBOXFS_INFO_GET | VBOXFS_INFO_VOLUME,
|
||||
volinfo, sizeof(*volinfo));
|
||||
|
||||
vboxfs_close_file(h);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Query volume information.
|
||||
*/
|
||||
int
|
||||
vboxfs_queryvol(char *path, u64_t *free, u64_t *total)
|
||||
{
|
||||
vboxfs_volinfo_t volinfo;
|
||||
int r;
|
||||
|
||||
if ((r = vboxfs_query_vol(path, &volinfo)) != OK)
|
||||
return r;
|
||||
|
||||
*free = volinfo.free;
|
||||
*total = volinfo.total;
|
||||
return OK;
|
||||
}
|
109
lib/libvboxfs/link.c
Normal file
109
lib/libvboxfs/link.c
Normal file
|
@ -0,0 +1,109 @@
|
|||
/* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
|
||||
|
||||
#include "inc.h"
|
||||
|
||||
/*
|
||||
* Create a directory.
|
||||
*/
|
||||
int
|
||||
vboxfs_mkdir(char *path, int mode)
|
||||
{
|
||||
vboxfs_handle_t h;
|
||||
int r;
|
||||
|
||||
assert(S_ISDIR(mode));
|
||||
|
||||
if ((r = vboxfs_open_file(path, O_CREAT | O_EXCL | O_WRONLY, mode, &h,
|
||||
NULL)) != OK)
|
||||
return r;
|
||||
|
||||
vboxfs_close_file(h);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a file or directory.
|
||||
*/
|
||||
static int
|
||||
remove_file(char *path, int dir)
|
||||
{
|
||||
vbox_param_t param[3];
|
||||
vboxfs_path_t pathbuf;
|
||||
int r;
|
||||
|
||||
if ((r = vboxfs_set_path(&pathbuf, path)) != OK)
|
||||
return r;
|
||||
|
||||
/* FIXME: symbolic links are not supported at all yet */
|
||||
vbox_set_u32(¶m[0], vboxfs_root);
|
||||
vbox_set_ptr(¶m[1], &pathbuf, vboxfs_get_path_size(&pathbuf),
|
||||
VBOX_DIR_OUT);
|
||||
vbox_set_u32(¶m[2], dir ? VBOXFS_REMOVE_DIR : VBOXFS_REMOVE_FILE);
|
||||
|
||||
return vbox_call(vboxfs_conn, VBOXFS_CALL_REMOVE, param, 3, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlink a file.
|
||||
*/
|
||||
int
|
||||
vboxfs_unlink(char *path)
|
||||
{
|
||||
|
||||
return remove_file(path, FALSE /*dir*/);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a directory.
|
||||
*/
|
||||
int
|
||||
vboxfs_rmdir(char *path)
|
||||
{
|
||||
|
||||
return remove_file(path, TRUE /*dir*/);
|
||||
}
|
||||
|
||||
/*
|
||||
* Rename a file or directory.
|
||||
*/
|
||||
static int
|
||||
rename_file(char *opath, char *npath, int dir)
|
||||
{
|
||||
vbox_param_t param[4];
|
||||
vboxfs_path_t opathbuf, npathbuf;
|
||||
u32_t flags;
|
||||
int r;
|
||||
|
||||
if ((r = vboxfs_set_path(&opathbuf, opath)) != OK)
|
||||
return r;
|
||||
|
||||
if ((r = vboxfs_set_path(&npathbuf, npath)) != OK)
|
||||
return r;
|
||||
|
||||
flags = dir ? VBOXFS_RENAME_DIR : VBOXFS_RENAME_FILE;
|
||||
flags |= VBOXFS_RENAME_REPLACE;
|
||||
|
||||
vbox_set_u32(¶m[0], vboxfs_root);
|
||||
vbox_set_ptr(¶m[1], &opathbuf, vboxfs_get_path_size(&opathbuf),
|
||||
VBOX_DIR_OUT);
|
||||
vbox_set_ptr(¶m[2], &npathbuf, vboxfs_get_path_size(&npathbuf),
|
||||
VBOX_DIR_OUT);
|
||||
vbox_set_u32(¶m[3], flags);
|
||||
|
||||
return vbox_call(vboxfs_conn, VBOXFS_CALL_RENAME, param, 4, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Rename a file or directory.
|
||||
*/
|
||||
int
|
||||
vboxfs_rename(char *opath, char *npath)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = rename_file(opath, npath, FALSE /*dir*/)) != EISDIR)
|
||||
return r;
|
||||
|
||||
return rename_file(opath, npath, TRUE /*dir*/);
|
||||
}
|
60
lib/libvboxfs/path.c
Normal file
60
lib/libvboxfs/path.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
|
||||
|
||||
#include "inc.h"
|
||||
|
||||
/*
|
||||
* Store a local path name in the given path object, performing any necessary
|
||||
* conversions. The path object is expected to be used read-only, so the size
|
||||
* of the path object is set as small as possible. If 'name' is NULL, the path
|
||||
* will be initialized to the empty string.
|
||||
*/
|
||||
int
|
||||
vboxfs_set_path(vboxfs_path_t *path, char *name)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = strlen(name);
|
||||
|
||||
/* FIXME: missing UTF-8 conversion */
|
||||
|
||||
if (len >= sizeof(path->data))
|
||||
return ENAMETOOLONG;
|
||||
|
||||
strcpy(path->data, name);
|
||||
|
||||
path->len = len;
|
||||
path->size = len + 1;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve the path name from the given path object. Make sure the name fits
|
||||
* in the given name buffer first. The given size must include room for a
|
||||
* terminating null character.
|
||||
*/
|
||||
int
|
||||
vboxfs_get_path(vboxfs_path_t *path, char *name, size_t size)
|
||||
{
|
||||
|
||||
/* FIXME: missing UTF-8 conversion */
|
||||
|
||||
if (path->len >= size)
|
||||
return ENAMETOOLONG;
|
||||
|
||||
assert(path->data[path->len] == 0);
|
||||
|
||||
strcpy(name, path->data);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the byte size of a previously initialized path object.
|
||||
*/
|
||||
size_t
|
||||
vboxfs_get_path_size(vboxfs_path_t *path)
|
||||
{
|
||||
|
||||
return offsetof(vboxfs_path_t, data) + path->size;
|
||||
}
|
46
lib/libvboxfs/proto.h
Normal file
46
lib/libvboxfs/proto.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
|
||||
|
||||
#ifndef _VBOXFS_PROTO_H
|
||||
#define _VBOXFS_PROTO_H
|
||||
|
||||
/* attr.c */
|
||||
void vboxfs_get_attr(struct sffs_attr *attr, vboxfs_objinfo_t *info);
|
||||
int vboxfs_getattr(char *path, struct sffs_attr *attr);
|
||||
int vboxfs_setattr(char *path, struct sffs_attr *attr);
|
||||
|
||||
/* dir.c */
|
||||
int vboxfs_opendir(char *path, sffs_dir_t *handle);
|
||||
int vboxfs_readdir(sffs_dir_t handle, unsigned int index, char *buf,
|
||||
size_t size, struct sffs_attr *attr);
|
||||
int vboxfs_closedir(sffs_dir_t handle);
|
||||
|
||||
/* file.c */
|
||||
int vboxfs_open(char *path, int flags, int mode, sffs_file_t *handle);
|
||||
ssize_t vboxfs_read(sffs_file_t handle, char *buf, size_t size, u64_t pos);
|
||||
ssize_t vboxfs_write(sffs_file_t handle, char *buf, size_t len, u64_t pos);
|
||||
int vboxfs_close(sffs_file_t handle);
|
||||
size_t vboxfs_buffer(char **ptr);
|
||||
|
||||
/* handle.c */
|
||||
int vboxfs_open_file(char *path, int flags, int mode, vboxfs_handle_t *handlep,
|
||||
vboxfs_objinfo_t *infop);
|
||||
void vboxfs_close_file(vboxfs_handle_t handle);
|
||||
|
||||
/* info.c */
|
||||
int vboxfs_getset_info(vboxfs_handle_t handle, u32_t flags, void *data,
|
||||
size_t size);
|
||||
int vboxfs_query_vol(char *path, vboxfs_volinfo_t *volinfo);
|
||||
int vboxfs_queryvol(char *path, u64_t *free, u64_t *total);
|
||||
|
||||
/* link.c */
|
||||
int vboxfs_mkdir(char *path, int mode);
|
||||
int vboxfs_unlink(char *path);
|
||||
int vboxfs_rmdir(char *path);
|
||||
int vboxfs_rename(char *opath, char *npath);
|
||||
|
||||
/* path.c */
|
||||
int vboxfs_set_path(vboxfs_path_t *path, char *name);
|
||||
int vboxfs_get_path(vboxfs_path_t *path, char *name, size_t size);
|
||||
size_t vboxfs_get_path_size(vboxfs_path_t *path);
|
||||
|
||||
#endif /* !_VBOXFS_PROTO_H */
|
98
lib/libvboxfs/vboxfs.c
Normal file
98
lib/libvboxfs/vboxfs.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
/* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
|
||||
|
||||
#include "inc.h"
|
||||
|
||||
vbox_conn_t vboxfs_conn;
|
||||
vboxfs_root_t vboxfs_root;
|
||||
|
||||
static struct sffs_table vboxfs_table = {
|
||||
.t_open = vboxfs_open,
|
||||
.t_read = vboxfs_read,
|
||||
.t_write = vboxfs_write,
|
||||
.t_close = vboxfs_close,
|
||||
|
||||
.t_readbuf = vboxfs_buffer,
|
||||
.t_writebuf = vboxfs_buffer,
|
||||
|
||||
.t_opendir = vboxfs_opendir,
|
||||
.t_readdir = vboxfs_readdir,
|
||||
.t_closedir = vboxfs_closedir,
|
||||
|
||||
.t_getattr = vboxfs_getattr,
|
||||
.t_setattr = vboxfs_setattr,
|
||||
|
||||
.t_mkdir = vboxfs_mkdir,
|
||||
.t_unlink = vboxfs_unlink,
|
||||
.t_rmdir = vboxfs_rmdir,
|
||||
.t_rename = vboxfs_rename,
|
||||
|
||||
.t_queryvol = vboxfs_queryvol
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize communication with the VBOX driver, and map the given share.
|
||||
*/
|
||||
int
|
||||
vboxfs_init(char *share, const struct sffs_table **tablep, int *case_insens,
|
||||
int *read_only)
|
||||
{
|
||||
vbox_param_t param[4];
|
||||
vboxfs_path_t path;
|
||||
vboxfs_volinfo_t volinfo;
|
||||
int r;
|
||||
|
||||
if ((r = vboxfs_set_path(&path, share)) != OK)
|
||||
return r;
|
||||
|
||||
if ((r = vbox_init()) != OK)
|
||||
return r;
|
||||
|
||||
if ((vboxfs_conn = r = vbox_open("VBoxSharedFolders")) < 0)
|
||||
return r;
|
||||
|
||||
r = vbox_call(vboxfs_conn, VBOXFS_CALL_SET_UTF8, NULL, 0, NULL);
|
||||
if (r != OK) {
|
||||
vbox_close(vboxfs_conn);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
vbox_set_ptr(¶m[0], &path, vboxfs_get_path_size(&path),
|
||||
VBOX_DIR_OUT);
|
||||
vbox_set_u32(¶m[1], 0);
|
||||
vbox_set_u32(¶m[2], '/'); /* path separator */
|
||||
vbox_set_u32(¶m[3], TRUE); /* case sensitivity - no effect? */
|
||||
|
||||
r = vbox_call(vboxfs_conn, VBOXFS_CALL_MAP_FOLDER, param, 4, NULL);
|
||||
if (r != OK) {
|
||||
vbox_close(vboxfs_conn);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
vboxfs_root = vbox_get_u32(¶m[1]);
|
||||
|
||||
/* Gather extra information about the mapped shared. */
|
||||
if (vboxfs_query_vol("", &volinfo) == OK) {
|
||||
*case_insens = !volinfo.props.casesens;
|
||||
*read_only = !!volinfo.props.readonly;
|
||||
}
|
||||
|
||||
*tablep = &vboxfs_table;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unmap the share, and disconnect from the VBOX driver.
|
||||
*/
|
||||
void
|
||||
vboxfs_cleanup(void)
|
||||
{
|
||||
vbox_param_t param[1];
|
||||
|
||||
vbox_set_u32(¶m[0], vboxfs_root);
|
||||
|
||||
vbox_call(vboxfs_conn, VBOXFS_CALL_UNMAP_FOLDER, param, 1, NULL);
|
||||
|
||||
vbox_close(vboxfs_conn);
|
||||
}
|
137
lib/libvboxfs/vboxfs.h
Normal file
137
lib/libvboxfs/vboxfs.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
/* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
|
||||
|
||||
#ifndef _VBOXFS_VBOXFS_H
|
||||
#define _VBOXFS_VBOXFS_H
|
||||
|
||||
#define VBOXFS_CALL_CREATE 3 /* create, open, lookup */
|
||||
#define VBOXFS_CALL_CLOSE 4 /* close handle */
|
||||
#define VBOXFS_CALL_READ 5 /* read from file */
|
||||
#define VBOXFS_CALL_WRITE 6 /* write to file */
|
||||
#define VBOXFS_CALL_LIST 8 /* list directory contents */
|
||||
#define VBOXFS_CALL_INFO 9 /* get/set file information */
|
||||
#define VBOXFS_CALL_REMOVE 11 /* remove file or directory */
|
||||
#define VBOXFS_CALL_UNMAP_FOLDER 13 /* unmap folder */
|
||||
#define VBOXFS_CALL_RENAME 14 /* rename file or directory */
|
||||
#define VBOXFS_CALL_SET_UTF8 16 /* switch to UTF8 */
|
||||
#define VBOXFS_CALL_MAP_FOLDER 17 /* map folder */
|
||||
|
||||
#define VBOXFS_INVALID_HANDLE ((vboxfs_handle_t) ~0LL)
|
||||
|
||||
typedef u32_t vboxfs_root_t;
|
||||
typedef u64_t vboxfs_handle_t;
|
||||
|
||||
typedef struct {
|
||||
u16_t size;
|
||||
u16_t len;
|
||||
char data[PATH_MAX];
|
||||
} vboxfs_path_t;
|
||||
|
||||
#define VBOXFS_NO_RESULT 0
|
||||
#define VBOXFS_PATH_NOT_FOUND 1
|
||||
#define VBOXFS_FILE_NOT_FOUND 2
|
||||
#define VBOXFS_FILE_EXISTS 3
|
||||
#define VBOXFS_FILE_CREATED 4
|
||||
#define VBOXFS_FILE_REPLACED 5
|
||||
|
||||
#define VBOXFS_OBJATTR_ADD_NONE 1 /* no other attributes */
|
||||
#define VBOXFS_OBJATTR_ADD_UNIX 2 /* POSIX attributes */
|
||||
#define VBOXFS_OBJATTR_ADD_EATTR 3 /* extended attributes */
|
||||
|
||||
typedef struct {
|
||||
u32_t mode;
|
||||
u32_t add;
|
||||
union {
|
||||
struct {
|
||||
u32_t uid;
|
||||
u32_t gid;
|
||||
u32_t nlinks;
|
||||
u32_t dev;
|
||||
u64_t inode;
|
||||
u32_t flags;
|
||||
u32_t gen;
|
||||
u32_t rdev;
|
||||
};
|
||||
struct {
|
||||
u64_t easize;
|
||||
};
|
||||
};
|
||||
} vboxfs_objattr_t;
|
||||
|
||||
/* Thankfully, MINIX uses the universal UNIX mode values. */
|
||||
#define VBOXFS_GET_MODE(mode) ((mode) & 0xffff)
|
||||
#define VBOXFS_SET_MODE(type, perm) ((type) | ((perm) & ALLPERMS))
|
||||
|
||||
typedef struct {
|
||||
u64_t size;
|
||||
u64_t disksize;
|
||||
u64_t atime;
|
||||
u64_t mtime;
|
||||
u64_t ctime;
|
||||
u64_t crtime;
|
||||
vboxfs_objattr_t attr;
|
||||
} vboxfs_objinfo_t;
|
||||
|
||||
#define VBOXFS_CRFLAG_LOOKUP 0x00000001
|
||||
#define VBOXFS_CRFLAG_DIRECTORY 0x00000004
|
||||
#define VBOXFS_CRFLAG_OPEN_IF_EXISTS 0x00000000
|
||||
#define VBOXFS_CRFLAG_FAIL_IF_EXISTS 0x00000010
|
||||
#define VBOXFS_CRFLAG_REPLACE_IF_EXISTS 0x00000020
|
||||
#define VBOXFS_CRFLAG_TRUNC_IF_EXISTS 0x00000030
|
||||
#define VBOXFS_CRFLAG_CREATE_IF_NEW 0x00000000
|
||||
#define VBOXFS_CRFLAG_FAIL_IF_NEW 0x00000100
|
||||
#define VBOXFS_CRFLAG_READ 0x00001000
|
||||
#define VBOXFS_CRFLAG_WRITE 0x00002000
|
||||
#define VBOXFS_CRFLAG_APPEND 0x00004000
|
||||
#define VBOXFS_CRFLAG_READ_ATTR 0x00010000
|
||||
#define VBOXFS_CRFLAG_WRITE_ATTR 0x00020000
|
||||
|
||||
typedef struct {
|
||||
vboxfs_handle_t handle;
|
||||
u32_t result;
|
||||
u32_t flags;
|
||||
vboxfs_objinfo_t info;
|
||||
} vboxfs_crinfo_t;
|
||||
|
||||
typedef struct {
|
||||
vboxfs_objinfo_t info;
|
||||
u16_t shortlen;
|
||||
u16_t shortname[14];
|
||||
vboxfs_path_t name; /* WARNING: name data size is dynamic! */
|
||||
} vboxfs_dirinfo_t;
|
||||
|
||||
#define VBOXFS_INFO_GET 0x00 /* get file information */
|
||||
#define VBOXFS_INFO_SET 0x01 /* set file information */
|
||||
|
||||
#define VBOXFS_INFO_SIZE 0x04 /* get/set file size */
|
||||
#define VBOXFS_INFO_FILE 0x08 /* get/set file attributes */
|
||||
#define VBOXFS_INFO_VOLUME 0x10 /* get volume information */
|
||||
|
||||
#define VBOXFS_REMOVE_FILE 0x01 /* remove file */
|
||||
#define VBOXFS_REMOVE_DIR 0x02 /* remove directory */
|
||||
#define VBOXFS_REMOVE_SYMLINK 0x04 /* remove symbolic link */
|
||||
|
||||
#define VBOXFS_RENAME_FILE 0x01 /* rename file */
|
||||
#define VBOXFS_RENAME_DIR 0x02 /* rename directory */
|
||||
#define VBOXFS_RENAME_REPLACE 0x04 /* replace target if it exists */
|
||||
|
||||
typedef struct {
|
||||
u32_t namemax;
|
||||
u8_t remote;
|
||||
u8_t casesens;
|
||||
u8_t readonly;
|
||||
u8_t unicode;
|
||||
u8_t fscomp;
|
||||
u8_t filecomp;
|
||||
u16_t reserved;
|
||||
} vboxfs_fsprops_t;
|
||||
|
||||
typedef struct {
|
||||
u64_t total;
|
||||
u64_t free;
|
||||
u32_t blocksize;
|
||||
u32_t sectorsize;
|
||||
u32_t serial;
|
||||
vboxfs_fsprops_t props;
|
||||
} vboxfs_volinfo_t;
|
||||
|
||||
#endif /* !_VBOXFS_VBOXFS_H */
|
|
@ -59,7 +59,7 @@ MKDEP_SUFFIXES?= .o .ln
|
|||
# rumpfs_tmpfs rumpfs_udf rumpfs_ufs
|
||||
.for _lib in \
|
||||
c curses blockdriver chardriver netdriver edit end m sys timers util \
|
||||
bz2 l audiodriver exec ddekit devman usb elf bdev sffs hgfs
|
||||
bz2 l audiodriver exec ddekit devman usb elf bdev sffs hgfs vboxfs
|
||||
.ifndef LIB${_lib:tu}
|
||||
LIB${_lib:tu}= ${DESTDIR}/usr/lib/lib${_lib}.a
|
||||
.MADE: ${LIB${_lib:tu}} # Note: ${DESTDIR} will be expanded
|
||||
|
|
Loading…
Reference in a new issue