vboxsf.c revision 9fc464631dc4a68fbb5eb6419d61fbe91b6b16bd
/* $Id$ */
/** @file
* Shared folders - Haiku Guest Additions, implementation.
*/
/*
* Copyright (C) 2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*
* This code is based on:
*
* VirtualBox Guest Additions for Haiku.
* Copyright (c) 2011 Mike Smith <mike@scgtrp.net>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "vboxsf.h"
#define MODULE_NAME "file_systems/vboxsf"
#define FS_NAME "vboxsf"
static fs_volume_ops vboxsf_volume_ops;
static fs_vnode_ops vboxsf_vnode_ops;
status_t init_module(void)
{
return B_ERROR;
}
if (RT_FAILURE(vboxInit())) {
dprintf("vboxInit failed\n");
return B_ERROR;
}
dprintf("vboxConnect failed\n");
return B_ERROR;
}
dprintf("vboxCallSetUtf8 failed\n");
return B_ERROR;
}
dprintf("warning: vboxCallSetSymlinks failed (old vbox?) - symlinks will appear as copies\n");
}
return B_OK;
}
void uninit_module(void)
{
}
PSHFLSTRING make_shflstring(const char* const s) {
if (len > 0xFFFE) {
return NULL;
}
if (!rv) {
return NULL;
}
return rv;
}
if (rv)
return rv;
}
if (rv) {
}
return rv;
}
if (rv) {
}
return rv;
}
return NULL;
if (rv) {
}
return rv;
}
status_t mount(fs_volume *volume, const char *device, uint32 flags, const char *args, ino_t *_rootVnodeID) {
if (device) {
return B_BAD_TYPE;
}
if (rv == 0) {
if (!name) {
return B_NO_MEMORY;
}
dprintf(FS_NAME ": allocated %p (path=%p name=%p)\n", root_vnode, root_vnode->path, root_vnode->name);
return rs;
}
return B_OK;
}
else {
return vbox_err_to_haiku_err(rv);
}
}
return B_OK;
}
int rc;
dprintf("vboxsf_read_stat (_vnode=%p, vnode=%p, path=%p (%s))\n", _vnode, vnode, vnode->path->String.utf8, vnode->path->String.utf8);
dprintf("sf_stat: calling vboxCallCreate, file %s, flags %x\n", vnode->path->String.utf8, params.CreateFlags);
if (rc == VERR_INVALID_NAME)
{
/* this can happen for names like 'foo*' on a Windows host */
return B_ENTRY_NOT_FOUND;
}
if (RT_FAILURE(rc))
{
}
{
return B_ENTRY_NOT_FOUND;
}
return B_OK;
}
if (RT_SUCCESS(rc)) {
cookie->has_more_files = true;
return B_OK;
}
else {
return B_ENTRY_NOT_FOUND;
}
}
else {
return vbox_err_to_haiku_err(rc);
}
}
/** read a single entry from a dir */
if (!cookie->has_more_files) {
return B_ENTRY_NOT_FOUND;
}
return vbox_err_to_haiku_err(rc);
}
if (rc == VERR_NO_MORE_FILES) {
cookie->has_more_files = false;
return B_ENTRY_NOT_FOUND;
}
}
dprintf("hit end of buffer\n");
return B_BUFFER_OVERFLOW;
}
if (!name1) {
return B_NO_MEMORY;
}
return rv;
}
// hit end of this buffer, next call will reallocate a new one
}
return B_OK;
}
// hit end of at least one of the buffers - not really an error
break;
}
}
return rv;
}
return B_OK;
}
if (RT_FAILURE(rc)) {
return vbox_err_to_haiku_err(rc);
}
return B_OK;
}
if (!path) {
return B_NO_MEMORY;
}
if (RT_SUCCESS(rc)) {
rv = publish_vnode(_volume, vn->vnode, vn, &vboxsf_vnode_ops, mode_from_fmode(params.Info.Attr.fMode), 0);
}
return rv;
}
else {
return B_ENTRY_NOT_FOUND;
}
}
else {
return vbox_err_to_haiku_err(rc);
}
}
mode_t m = 0;
if (RTFS_IS_DIRECTORY(fMode))
m |= S_IFDIR;
else if (RTFS_IS_FILE(fMode))
m |= S_IFREG;
else if (RTFS_IS_FIFO(fMode))
m |= S_IFIFO;
else if (RTFS_IS_DEV_CHAR(fMode))
m |= S_IFCHR;
else if (RTFS_IS_DEV_BLOCK(fMode))
m |= S_IFBLK;
else if (RTFS_IS_SYMLINK(fMode))
m |= S_IFLNK;
else if (RTFS_IS_SOCKET(fMode))
m |= S_IFSOCK;
if (fMode & RTFS_UNIX_IRUSR)
m |= S_IRUSR;
if (fMode & RTFS_UNIX_IWUSR)
m |= S_IWUSR;
if (fMode & RTFS_UNIX_IXUSR)
m |= S_IXUSR;
if (fMode & RTFS_UNIX_IRGRP)
m |= S_IRGRP;
if (fMode & RTFS_UNIX_IWGRP)
m |= S_IWGRP;
if (fMode & RTFS_UNIX_IXGRP)
m |= S_IXGRP;
if (fMode & RTFS_UNIX_IROTH)
m |= S_IROTH;
if (fMode & RTFS_UNIX_IWOTH)
m |= S_IWOTH;
if (fMode & RTFS_UNIX_IXOTH)
m |= S_IXOTH;
if (fMode & RTFS_UNIX_ISUID)
m |= S_ISUID;
if (fMode & RTFS_UNIX_ISGID)
m |= S_ISGID;
if (fMode & RTFS_UNIX_ISTXT)
m |= S_ISVTX;
return m;
}
else
}
else {
else
}
if (!RT_SUCCESS(rc)) {
return vbox_err_to_haiku_err(rc);
}
if (!cookie) {
dprintf("couldn't allocate file cookie\n");
return B_NO_MEMORY;
}
return B_OK;
}
status_t vboxsf_create(fs_volume* _volume, fs_vnode* _dir, const char *name, int openMode, int perms, void **_cookie, ino_t *_newVnodeID) {
else
}
else {
else
}
if (!RT_SUCCESS(rc)) {
return vbox_err_to_haiku_err(rc);
}
if (!cookie) {
dprintf("couldn't allocate file cookie\n");
return B_NO_MEMORY;
}
}
return vbox_err_to_haiku_err(rc);
}
return B_OK;
}
return B_OK;
}
return B_OK;
}
status_t vboxsf_read(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, off_t pos, void *buffer, size_t *length) {
if (*length > 0xFFFFFFFF) {
*length = 0xFFFFFFFF;
}
*length = l;
return vbox_err_to_haiku_err(rc);
}
status_t vboxsf_write(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, off_t pos, const void *buffer, size_t *length) {
if (*length > 0xFFFFFFFF) {
*length = 0xFFFFFFFF;
}
int rc = vboxCallWrite(&g_clientHandle, &volume->map, cookie->handle, pos, &l, other_buffer, false);
*length = l;
return vbox_err_to_haiku_err(rc);
}
status_t vboxsf_write_stat(fs_volume *volume, fs_vnode *vnode, const struct stat *stat, uint32 statMask) {
// the host handles updating the stat info - in the guest, this is a no-op
return B_OK;
}
return vbox_err_to_haiku_err(rc);
}
else {
return B_OK;
}
}
return vbox_err_to_haiku_err(rc);
}
return vbox_err_to_haiku_err(rc);
}
return B_UNSUPPORTED;
}
status_t vboxsf_rename(fs_volume* _volume, fs_vnode* fromDir, const char* fromName, fs_vnode* toDir, const char* toName) {
int rc = vboxCallRename(&g_clientHandle, &volume->map, oldpath, newpath, SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS);
return vbox_err_to_haiku_err(rc);
}
status_t vboxsf_create_symlink(fs_volume* _volume, fs_vnode* dir, const char* name, const char* path, int mode) {
return vbox_err_to_haiku_err(rc);
}
status_t vboxsf_read_symlink(fs_volume* _volume, fs_vnode* link, char* buffer, size_t* _bufferSize) {
return vbox_err_to_haiku_err(rc);
}
// TODO move this into the runtime
switch (rc) {
case VINF_SUCCESS: return B_OK;
case VERR_INVALID_POINTER: return B_BAD_ADDRESS;
case VERR_INVALID_PARAMETER: return B_BAD_VALUE;
case VERR_PERMISSION_DENIED: return B_PERMISSION_DENIED;
case VERR_NOT_IMPLEMENTED: return B_UNSUPPORTED;
case VERR_FILE_NOT_FOUND: return B_ENTRY_NOT_FOUND;
case SHFL_FILE_EXISTS: return B_FILE_EXISTS;
case SHFL_PATH_NOT_FOUND:
case SHFL_FILE_NOT_FOUND: return B_ENTRY_NOT_FOUND;
default: return B_ERROR;
}
}
switch(op) {
case B_MODULE_INIT:
return init_module();
case B_MODULE_UNINIT:
return B_OK;
default:
return B_ERROR;
}
}
static fs_volume_ops vboxsf_volume_ops = {
vboxsf_read_fs_info, // read_fs_info
NULL, // write_fs_info
NULL, // sync
vboxsf_get_vnode, // get_vnode
NULL, // open_index_dir
NULL, // close_index_dir
NULL, // free_index_dir_cookie
NULL, // read_index_dir
NULL, // rewind_index_dir
NULL, // create_index
NULL, // remove_index
NULL, // read_index_stat
NULL, // open_query
NULL, // close_query
NULL, // free_query_cookie
NULL, // read_query
NULL, // rewind_query
NULL, // all_layers_mounted
NULL, // create_sub_vnode
NULL, // delete_sub_vnode
};
static fs_vnode_ops vboxsf_vnode_ops = {
vboxsf_lookup, // lookup
NULL, // get_vnode_name
vboxsf_put_vnode, // put_vnode
NULL, // remove_vnode
NULL, // can_page
NULL, // read_pages
NULL, // write_pages
NULL, // io
NULL, // cancel_io
NULL, // get_file_map
NULL, // ioctl
NULL, // set_flags
NULL, // select
NULL, // deselect
NULL, // fsync
vboxsf_read_symlink, // read_symlink
vboxsf_create_symlink, // create_symlink
vboxsf_link, // link
vboxsf_unlink, // unlink
vboxsf_rename, // rename
NULL, // access
vboxsf_read_stat, // read_stat
vboxsf_write_stat, // write_stat
NULL, // preallocate
vboxsf_create, // create
vboxsf_open, // open
vboxsf_close, // close
vboxsf_free_cookie, // free_cookie
vboxsf_read, // read
vboxsf_write, // write
vboxsf_create_dir, // create_dir
vboxsf_remove_dir, // remove_dir
vboxsf_open_dir, // open_dir
vboxsf_close_dir, // close_dir
vboxsf_free_dir_cookie, // free_dir_cookie
vboxsf_read_dir, // read_dir
vboxsf_rewind_dir, // rewind_dir
NULL, // open_attr_dir
NULL, // close_attr_dir
NULL, // free_attr_dir_cookie
NULL, // read_attr_dir
NULL, // rewind_attr_dir
NULL, // create_attr
NULL, // open_attr
NULL, // close_attr
NULL, // free_attr_cookie
NULL, // read_attr
NULL, // write_attr
NULL, // read_attr_stat
NULL, // write_attr_stat
NULL, // rename_attr
NULL, // remove_attr
NULL, // create_special_node
NULL, // get_super_vnode
};
static file_system_module_info sVBoxSharedFileSystem = {
{
0,
},
FS_NAME, // short_name
"VirtualBox shared folders", // pretty_name
0, //B_DISK_SYSTEM_SUPPORTS_WRITING, // DDM flags
// scanning
NULL, // identify_partition
NULL, // scan_partition
NULL, // free_identify_partition_cookie
NULL, // free_partition_content_cookie()
};
module_info *modules[] = {
NULL,
};