diff options
Diffstat (limited to 'src/VBox/Additions/freebsd/vboxvfs')
-rw-r--r-- | src/VBox/Additions/freebsd/vboxvfs/Makefile.kmk | 74 | ||||
-rw-r--r-- | src/VBox/Additions/freebsd/vboxvfs/vboxvfs.h | 105 | ||||
-rw-r--r-- | src/VBox/Additions/freebsd/vboxvfs/vboxvfs_vfsops.c | 268 | ||||
-rw-r--r-- | src/VBox/Additions/freebsd/vboxvfs/vboxvfs_vnops.c | 251 |
4 files changed, 698 insertions, 0 deletions
diff --git a/src/VBox/Additions/freebsd/vboxvfs/Makefile.kmk b/src/VBox/Additions/freebsd/vboxvfs/Makefile.kmk new file mode 100644 index 00000000..8931fef8 --- /dev/null +++ b/src/VBox/Additions/freebsd/vboxvfs/Makefile.kmk @@ -0,0 +1,74 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-Makefile for the FreeBSD Shared folder kernel module. +# + +# +# Copyright (C) 2007-2022 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses>. +# +# SPDX-License-Identifier: GPL-3.0-only +# + +SUB_DEPTH = ../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +ifneq ($(KBUILD_HOST),freebsd) +$(error "The FreeBSD guest additions can only be built on FreeBSD!") +endif + +# +# vboxvfs - The Shared Folder Driver +# +SYSMODS.freebsd += vboxvfs +vboxvfs_TEMPLATE = VBOXGUESTR0 +vboxvfs_DEFS = VBOX_WITH_HGCM +vboxvfs_INCS = \ + . \ + $(vboxvfs_0_OUTDIR) +vboxvfs_SOURCES = \ + vboxvfs_vfsops.c \ + vboxvfs_vnops.c +vboxvfs_LIBS = \ + $(VBOX_LIB_VBGL_R0) \ + $(VBOX_LIB_IPRT_GUEST_R0) +vboxvfs_DEPS = \ + $$(vboxvfs_0_OUTDIR)/vnode_if.h \ + $$(vboxvfs_0_OUTDIR)/vnode_if_newproto.h \ + $$(vboxvfs_0_OUTDIR)/vnode_if_typedef.h +vboxvfs_CLEAN += $(vboxvfs_DEPS) + +VBOX_AWK := /usr/bin/awk + +$$(vboxvfs_0_OUTDIR)/vnode_if.h: $(VBOX_FREEBSD_SRC)/kern/vnode_if.src + $(call MSG_TOOL,awk,VBoxGuest,$<,$@) + $(QUIET)$(VBOX_AWK) -f $(VBOX_FREEBSD_SRC)/tools/vnode_if.awk $(VBOX_FREEBSD_SRC)/kern/vnode_if.src -h + $(QUIET)$(MV) $(vboxvfs_0_OUTDIR)/vnode_if.h $(vboxvfs_0_OUTDIR)/vnode_if.h + +$$(vboxvfs_0_OUTDIR)/vnode_if_newproto.h: $(VBOX_FREEBSD_SRC)/kern/vnode_if.src + $(call MSG_TOOL,awk,VBoxGuest,$<,$@) + $(QUIET)$(VBOX_AWK) -f $(VBOX_FREEBSD_SRC)/tools/vnode_if.awk $(VBOX_FREEBSD_SRC)/kern/vnode_if.src -p + $(QUIET)$(MV) $(vboxvfs_0_OUTDIR)/vnode_if_newproto.h $(vboxvfs_0_OUTDIR)/vnode_if_newproto.h + +$$(vboxvfs_0_OUTDIR)/vnode_if_typedef.h: $(VBOX_FREEBSD_SRC)/kern/vnode_if.src + $(call MSG_TOOL,awk,VBoxGuest,$<,$@) + $(QUIET)$(VBOX_AWK) -f $(VBOX_FREEBSD_SRC)/tools/vnode_if.awk $(VBOX_FREEBSD_SRC)/kern/vnode_if.src -q + $(QUIET)$(MV) $(vboxvfs_0_OUTDIR)/vnode_if_typedef.h $(vboxvfs_0_OUTDIR)/vnode_if_typedef.h + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Additions/freebsd/vboxvfs/vboxvfs.h b/src/VBox/Additions/freebsd/vboxvfs/vboxvfs.h new file mode 100644 index 00000000..6c00c776 --- /dev/null +++ b/src/VBox/Additions/freebsd/vboxvfs/vboxvfs.h @@ -0,0 +1,105 @@ +/* $Id: vboxvfs.h $ */ +/** @file + * Description. + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef GA_INCLUDED_SRC_freebsd_vboxvfs_vboxvfs_h +#define GA_INCLUDED_SRC_freebsd_vboxvfs_vboxvfs_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#define VBOXVFS_VFSNAME "vboxvfs" +#define VBOXVFS_VERSION 1 + +#define MAX_HOST_NAME 256 +#define MAX_NLS_NAME 32 + +struct vboxvfs_mount_info { + char name[MAX_HOST_NAME]; + char nls_name[MAX_NLS_NAME]; + int uid; + int gid; + int ttl; +}; + +#ifdef _KERNEL + +#include <VBox/VBoxGuestLibSharedFolders.h> +#include <sys/mount.h> +#include <sys/vnode.h> + +struct vboxvfsmount { + uid_t uid; + gid_t gid; + mode_t file_mode; + mode_t dir_mode; + struct mount *mp; + struct ucred *owner; + u_int flags; + long nextino; + int caseopt; + int didrele; +}; + +/* structs - stolen from the linux shared module code */ +struct sf_glob_info { + VBGLSFMAP map; +/* struct nls_table *nls;*/ + int ttl; + int uid; + int gid; + struct vnode *vnode_root; +}; + +struct sf_inode_info { + SHFLSTRING *path; + int force_restat; +}; + +#if 0 +struct sf_dir_info { + struct list_head info_list; +}; +#endif + +struct sf_dir_buf { + size_t nb_entries; + size_t free_bytes; + size_t used_bytes; + void *buf; +#if 0 + struct list_head head; +#endif +}; + +struct sf_reg_info { + SHFLHANDLE handle; +}; + +#endif /* KERNEL */ + +#endif /* !GA_INCLUDED_SRC_freebsd_vboxvfs_vboxvfs_h */ + diff --git a/src/VBox/Additions/freebsd/vboxvfs/vboxvfs_vfsops.c b/src/VBox/Additions/freebsd/vboxvfs/vboxvfs_vfsops.c new file mode 100644 index 00000000..ff190c7e --- /dev/null +++ b/src/VBox/Additions/freebsd/vboxvfs/vboxvfs_vfsops.c @@ -0,0 +1,268 @@ +/* $Id: vboxvfs_vfsops.c $ */ +/** @file + * Description. + */ + +/* + * Copyright (C) 2008-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include "vboxvfs.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/bio.h> +#include <sys/buf.h> +#include <sys/kernel.h> +#include <sys/sysctl.h> +#include <sys/vnode.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <sys/malloc.h> +#include <sys/module.h> + +#include <iprt/mem.h> + +#define VFSMP2SFGLOBINFO(mp) ((struct sf_glob_info *)mp->mnt_data) + +static int vboxvfs_version = VBOXVFS_VERSION; + +SYSCTL_NODE(_vfs, OID_AUTO, vboxvfs, CTLFLAG_RW, 0, "VirtualBox shared filesystem"); +SYSCTL_INT(_vfs_vboxvfs, OID_AUTO, version, CTLFLAG_RD, &vboxvfs_version, 0, ""); + +/* global connection to the host service. */ +static VBGLSFCLIENT g_vboxSFClient; + +static vfs_init_t vboxvfs_init; +static vfs_uninit_t vboxvfs_uninit; +static vfs_cmount_t vboxvfs_cmount; +static vfs_mount_t vboxvfs_mount; +static vfs_root_t vboxvfs_root; +static vfs_quotactl_t vboxvfs_quotactl; +static vfs_statfs_t vboxvfs_statfs; +static vfs_unmount_t vboxvfs_unmount; + +static struct vfsops vboxvfs_vfsops = { + .vfs_init = vboxvfs_init, + .vfs_cmount = vboxvfs_cmount, + .vfs_mount = vboxvfs_mount, + .vfs_quotactl = vboxvfs_quotactl, + .vfs_root = vboxvfs_root, + .vfs_statfs = vboxvfs_statfs, + .vfs_sync = vfs_stdsync, + .vfs_uninit = vboxvfs_uninit, + .vfs_unmount = vboxvfs_unmount, +}; + + +VFS_SET(vboxvfs_vfsops, vboxvfs, VFCF_NETWORK); +MODULE_DEPEND(vboxvfs, vboxguest, 1, 1, 1); + +static int vboxvfs_cmount(struct mntarg *ma, void * data, int flags, struct thread *td) +{ + struct vboxvfs_mount_info args; + int rc = 0; + + printf("%s: Enter\n", __FUNCTION__); + + rc = copyin(data, &args, sizeof(struct vboxvfs_mount_info)); + if (rc) + return rc; + + ma = mount_argf(ma, "uid", "%d", args.uid); + ma = mount_argf(ma, "gid", "%d", args.gid); + ma = mount_arg(ma, "from", args.name, -1); + + rc = kernel_mount(ma, flags); + + printf("%s: Leave rc=%d\n", __FUNCTION__, rc); + + return rc; +} + +static const char *vboxvfs_opts[] = { + "uid", "gid", "from", "fstype", "fspath", "errmsg", NULL +}; + +static int vboxvfs_mount(struct mount *mp, struct thread *td) +{ + int rc; + char *pszShare; + int cbShare, cbOption; + int uid = 0, gid = 0; + struct sf_glob_info *pShFlGlobalInfo; + SHFLSTRING *pShFlShareName = NULL; + int cbShFlShareName; + + printf("%s: Enter\n", __FUNCTION__); + + if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS)) + return EOPNOTSUPP; + + if (vfs_filteropt(mp->mnt_optnew, vboxvfs_opts)) + { + vfs_mount_error(mp, "%s", "Invalid option"); + return EINVAL; + } + + rc = vfs_getopt(mp->mnt_optnew, "from", (void **)&pszShare, &cbShare); + if (rc || pszShare[cbShare-1] != '\0' || cbShare > 0xfffe) + return EINVAL; + + rc = vfs_getopt(mp->mnt_optnew, "gid", (void **)&gid, &cbOption); + if ((rc != ENOENT) && (rc || cbOption != sizeof(gid))) + return EINVAL; + + rc = vfs_getopt(mp->mnt_optnew, "uid", (void **)&uid, &cbOption); + if ((rc != ENOENT) && (rc || cbOption != sizeof(uid))) + return EINVAL; + + pShFlGlobalInfo = RTMemAllocZ(sizeof(struct sf_glob_info)); + if (!pShFlGlobalInfo) + return ENOMEM; + + cbShFlShareName = offsetof (SHFLSTRING, String.utf8) + cbShare + 1; + pShFlShareName = RTMemAllocZ(cbShFlShareName); + if (!pShFlShareName) + return VERR_NO_MEMORY; + + pShFlShareName->u16Length = cbShare; + pShFlShareName->u16Size = cbShare + 1; + memcpy (pShFlShareName->String.utf8, pszShare, cbShare + 1); + + rc = VbglR0SfMapFolder (&g_vboxSFClient, pShFlShareName, &pShFlGlobalInfo->map); + RTMemFree(pShFlShareName); + + if (RT_FAILURE (rc)) + { + RTMemFree(pShFlGlobalInfo); + printf("VbglR0SfMapFolder failed rc=%d\n", rc); + return EPROTO; + } + + pShFlGlobalInfo->uid = uid; + pShFlGlobalInfo->gid = gid; + + mp->mnt_data = pShFlGlobalInfo; + + /** @todo root vnode. */ + + vfs_getnewfsid(mp); + vfs_mountedfrom(mp, pszShare); + + printf("%s: Leave rc=0\n", __FUNCTION__); + + return 0; +} + +static int vboxvfs_unmount(struct mount *mp, int mntflags, struct thread *td) +{ + struct sf_glob_info *pShFlGlobalInfo = VFSMP2SFGLOBINFO(mp); + int rc; + int flags = 0; + + rc = VbglR0SfUnmapFolder(&g_vboxSFClient, &pShFlGlobalInfo->map); + if (RT_FAILURE(rc)) + printf("Failed to unmap shared folder\n"); + + if (mntflags & MNT_FORCE) + flags |= FORCECLOSE; + + /* There is 1 extra root vnode reference (vnode_root). */ + rc = vflush(mp, 1, flags, td); + if (rc) + return rc; + + + RTMemFree(pShFlGlobalInfo); + mp->mnt_data = NULL; + + return 0; +} + +static int vboxvfs_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td) +{ + int rc = 0; + struct sf_glob_info *pShFlGlobalInfo = VFSMP2SFGLOBINFO(mp); + struct vnode *vp; + + printf("%s: Enter\n", __FUNCTION__); + + vp = pShFlGlobalInfo->vnode_root; + VREF(vp); + + vn_lock(vp, flags | LK_RETRY, td); + *vpp = vp; + + printf("%s: Leave\n", __FUNCTION__); + + return rc; +} + +static int vboxvfs_quotactl(struct mount *mp, int cmd, uid_t uid, void *arg, struct thread *td) +{ + return EOPNOTSUPP; +} + +int vboxvfs_init(struct vfsconf *vfsp) +{ + int rc; + + /* Initialize the R0 guest library. */ + rc = VbglR0SfInit(); + if (RT_FAILURE(rc)) + return ENXIO; + + /* Connect to the host service. */ + rc = VbglR0SfConnect(&g_vboxSFClient); + if (RT_FAILURE(rc)) + { + printf("Failed to get connection to host! rc=%d\n", rc); + VbglR0SfTerm(); + return ENXIO; + } + + rc = VbglR0SfSetUtf8(&g_vboxSFClient); + if (RT_FAILURE (rc)) + { + printf("VbglR0SfSetUtf8 failed, rc=%d\n", rc); + VbglR0SfDisconnect(&g_vboxSFClient); + VbglR0SfTerm(); + return EPROTO; + } + + printf("Successfully loaded shared folder module\n"); + + return 0; +} + +int vboxvfs_uninit(struct vfsconf *vfsp) +{ + VbglR0SfDisconnect(&g_vboxSFClient); + VbglR0SfTerm(); + + return 0; +} + +int vboxvfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td) +{ + return 0; +} diff --git a/src/VBox/Additions/freebsd/vboxvfs/vboxvfs_vnops.c b/src/VBox/Additions/freebsd/vboxvfs/vboxvfs_vnops.c new file mode 100644 index 00000000..1eb9cdf9 --- /dev/null +++ b/src/VBox/Additions/freebsd/vboxvfs/vboxvfs_vnops.c @@ -0,0 +1,251 @@ +/* $Id: vboxvfs_vnops.c $ */ +/** @file + * Description. + */ + +/* + * Copyright (C) 2008-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include "vboxvfs.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/namei.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/bio.h> +#include <sys/buf.h> +#include <sys/fcntl.h> +#include <sys/mount.h> +#include <sys/unistd.h> +#include <sys/vnode.h> +#include <sys/limits.h> +#include <sys/lockf.h> +#include <sys/stat.h> + +#include <vm/vm.h> +#include <vm/vm_extern.h> + +/* + * Prototypes for VBOXVFS vnode operations + */ +static vop_create_t vboxvfs_create; +static vop_mknod_t vboxvfs_mknod; +static vop_open_t vboxvfs_open; +static vop_close_t vboxvfs_close; +static vop_access_t vboxvfs_access; +static vop_getattr_t vboxvfs_getattr; +static vop_setattr_t vboxvfs_setattr; +static vop_read_t vboxvfs_read; +static vop_write_t vboxvfs_write; +static vop_fsync_t vboxvfs_fsync; +static vop_remove_t vboxvfs_remove; +static vop_link_t vboxvfs_link; +static vop_lookup_t vboxvfs_lookup; +static vop_rename_t vboxvfs_rename; +static vop_mkdir_t vboxvfs_mkdir; +static vop_rmdir_t vboxvfs_rmdir; +static vop_symlink_t vboxvfs_symlink; +static vop_readdir_t vboxvfs_readdir; +static vop_strategy_t vboxvfs_strategy; +static vop_print_t vboxvfs_print; +static vop_pathconf_t vboxvfs_pathconf; +static vop_advlock_t vboxvfs_advlock; +static vop_getextattr_t vboxvfs_getextattr; +static vop_ioctl_t vboxvfs_ioctl; +static vop_getpages_t vboxvfs_getpages; +static vop_inactive_t vboxvfs_inactive; +static vop_putpages_t vboxvfs_putpages; +static vop_reclaim_t vboxvfs_reclaim; + +struct vop_vector vboxvfs_vnodeops = { + .vop_default = &default_vnodeops, + + .vop_access = vboxvfs_access, + .vop_advlock = vboxvfs_advlock, + .vop_close = vboxvfs_close, + .vop_create = vboxvfs_create, + .vop_fsync = vboxvfs_fsync, + .vop_getattr = vboxvfs_getattr, + .vop_getextattr = vboxvfs_getextattr, + .vop_getpages = vboxvfs_getpages, + .vop_inactive = vboxvfs_inactive, + .vop_ioctl = vboxvfs_ioctl, + .vop_link = vboxvfs_link, + .vop_lookup = vboxvfs_lookup, + .vop_mkdir = vboxvfs_mkdir, + .vop_mknod = vboxvfs_mknod, + .vop_open = vboxvfs_open, + .vop_pathconf = vboxvfs_pathconf, + .vop_print = vboxvfs_print, + .vop_putpages = vboxvfs_putpages, + .vop_read = vboxvfs_read, + .vop_readdir = vboxvfs_readdir, + .vop_reclaim = vboxvfs_reclaim, + .vop_remove = vboxvfs_remove, + .vop_rename = vboxvfs_rename, + .vop_rmdir = vboxvfs_rmdir, + .vop_setattr = vboxvfs_setattr, + .vop_strategy = vboxvfs_strategy, + .vop_symlink = vboxvfs_symlink, + .vop_write = vboxvfs_write, +}; + +static int vboxvfs_access(struct vop_access_args *ap) +{ + return 0; +} + +static int vboxvfs_open(struct vop_open_args *ap) +{ + return 0; +} + +static int vboxvfs_close(struct vop_close_args *ap) +{ + return 0; +} + +static int vboxvfs_getattr(struct vop_getattr_args *ap) +{ + return 0; +} + +static int vboxvfs_setattr(struct vop_setattr_args *ap) +{ + return 0; +} + +static int vboxvfs_read(struct vop_read_args *ap) +{ + return 0; +} + +static int vboxvfs_write(struct vop_write_args *ap) +{ + return 0; +} + +static int vboxvfs_create(struct vop_create_args *ap) +{ + return 0; +} + +static int vboxvfs_remove(struct vop_remove_args *ap) +{ + return 0; +} + +static int vboxvfs_rename(struct vop_rename_args *ap) +{ + return 0; +} + +static int vboxvfs_link(struct vop_link_args *ap) +{ + return EOPNOTSUPP; +} + +static int vboxvfs_symlink(struct vop_symlink_args *ap) +{ + return EOPNOTSUPP; +} + +static int vboxvfs_mknod(struct vop_mknod_args *ap) +{ + return EOPNOTSUPP; +} + +static int vboxvfs_mkdir(struct vop_mkdir_args *ap) +{ + return 0; +} + +static int vboxvfs_rmdir(struct vop_rmdir_args *ap) +{ + return 0; +} + +static int vboxvfs_readdir(struct vop_readdir_args *ap) +{ + return 0; +} + +static int vboxvfs_fsync(struct vop_fsync_args *ap) +{ + return 0; +} + +static int vboxvfs_print (struct vop_print_args *ap) +{ + return 0; +} + +static int vboxvfs_pathconf (struct vop_pathconf_args *ap) +{ + return 0; +} + +static int vboxvfs_strategy (struct vop_strategy_args *ap) +{ + return 0; +} + +static int vboxvfs_ioctl(struct vop_ioctl_args *ap) +{ + return ENOTTY; +} + +static int vboxvfs_getextattr(struct vop_getextattr_args *ap) +{ + return 0; +} + +static int vboxvfs_advlock(struct vop_advlock_args *ap) +{ + return 0; +} + +static int vboxvfs_lookup(struct vop_lookup_args *ap) +{ + return 0; +} + +static int vboxvfs_inactive(struct vop_inactive_args *ap) +{ + return 0; +} + +static int vboxvfs_reclaim(struct vop_reclaim_args *ap) +{ + return 0; +} + +static int vboxvfs_getpages(struct vop_getpages_args *ap) +{ + return 0; +} + +static int vboxvfs_putpages(struct vop_putpages_args *ap) +{ + return 0; +} + |