utils.c revision aa9eecc1b20f1a9d5ef527d054af454a08879a9d
e35e9d6317da2985728e7510bea9337b9893b66evboxsync * vboxvfs -- VirtualBox Guest Additions for Linux:
e35e9d6317da2985728e7510bea9337b9893b66evboxsync * Utility functions.
e35e9d6317da2985728e7510bea9337b9893b66evboxsync * Mainly conversion from/to VirtualBox/Linux data structures
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * available from http://www.virtualbox.org. This file is free software;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * you can redistribute it and/or modify it under the terms of the GNU
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * General Public License (GPL) as published by the Free Software
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
e35e9d6317da2985728e7510bea9337b9893b66evboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
e35e9d6317da2985728e7510bea9337b9893b66evboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
f52596ee352b88100d0a2abd044c8edd3c542bd7vboxsync * additional information or have any questions.
08122b11035de1e54ce1e665dff7260fc548db72vboxsync/* #define USE_VMALLOC */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * sf_reg_aops and sf_backing_dev_info are just quick implementations to make
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * sendfile work. For more information have a look at
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * http://us1.samba.org/samba/ftp/cifs-cvs/ols2006-fs-tutorial-smf.odp
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * and the sample implementation
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * http://pserver.samba.org/samba/ftp/cifs-cvs/samplefs.tar.gz
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncstatic struct backing_dev_info sf_backing_dev_info = {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync# if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 12)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync .capabilities = BDI_CAP_MAP_DIRECT /* MAP_SHARED */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync | BDI_CAP_WRITE_MAP /* can be mapped for writing */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync | BDI_CAP_EXEC_MAP, /* can be mapped for execution */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 0) */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncsf_ftime_from_timespec (time_t *time, RTTIMESPEC *ts)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncsf_ftime_from_timespec (struct timespec *tv, RTTIMESPEC *ts)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync/* set [inode] attributes based on [info], uid/gid based on [sf_g] */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncsf_init_inode (struct sf_glob_info *sf_g, struct inode *inode,
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync#define mode_set(r) attr->fMode & (RTFS_UNIX_##r) ? (S_##r) : 0;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync inode->i_mapping->backing_dev_info = &sf_backing_dev_info;
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync inode->i_mode = sf_g->dmode != ~0 ? (sf_g->dmode & 0777) : mode;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync /* XXX: this probably should be set to the number of entries
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync in the directory plus two (. ..) */
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync inode->i_mode = sf_g->fmode != ~0 ? (sf_g->fmode & 0x777): mode;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 19) && !defined(KERNEL_FC6)
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync sf_ftime_from_timespec (&inode->i_atime, &info->AccessTime);
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync sf_ftime_from_timespec (&inode->i_ctime, &info->ChangeTime);
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync sf_ftime_from_timespec (&inode->i_mtime, &info->ModificationTime);
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsyncsf_stat (const char *caller, struct sf_glob_info *sf_g,
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync SHFLSTRING *path, RTFSOBJINFO *result, int ok_to_fail)
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync params.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync LogFunc(("calling vboxCallCreate, file %s, flags %#x\n",
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync rc = vboxCallCreate (&client_handle, &sf_g->map, path, ¶ms);
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync LogFunc(("vboxCallCreate(%s) failed. caller=%s, rc=%Vrc\n",
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync LogFunc(("vboxCallCreate(%s) file does not exist. caller=%s, result=%d\n",
a7f701e8c51193f7c21137cc173ea5f86e53cac2vboxsync/* this is called directly as iop on 2.4, indirectly as dop
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync [sf_dentry_revalidate] on 2.4/2.6, indirectly as iop through
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync [sf_getattr] on 2.6. the job is to find out whether dentry/inode is
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync still valid. the test is failed if [dentry] does not have an inode
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync or [sf_stat] is unsuccessful, otherwise we return success and
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync update inode attributes */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync LogFunc(("no dentry(%p) or inode(%p)\n", dentry, dentry->d_inode));
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync err = sf_stat (__func__, sf_g, sf_i->path, &info, 1);
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync/* this is called during name resolution/lookup to check if the
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync [dentry] in the cache is still valid. the job is handled by
5cb8545771849c97101a5ee9bb57d0fdac922c44vboxsync [sf_inode_revalidate] */
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsyncsf_dentry_revalidate (struct dentry *dentry, int flags)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync sf_dentry_revalidate (struct dentry *dentry, struct nameidata *nd)
e35e9d6317da2985728e7510bea9337b9893b66evboxsync/* on 2.6 this is a proxy for [sf_inode_revalidate] which (as a side
e35e9d6317da2985728e7510bea9337b9893b66evboxsync effect) updates inode attributes for [dentry] (given that [dentry]
e35e9d6317da2985728e7510bea9337b9893b66evboxsync has inode at all) from these new attributes we derive [kstat] via
e35e9d6317da2985728e7510bea9337b9893b66evboxsync [generic_fillattr] */
e35e9d6317da2985728e7510bea9337b9893b66evboxsyncsf_getattr (struct vfsmount *mnt, struct dentry *dentry, struct kstat *kstat)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncsf_make_path (const char *caller, struct sf_inode_info *sf_i,
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync const char *d_name, size_t d_len, SHFLSTRING **result)
e35e9d6317da2985728e7510bea9337b9893b66evboxsync /* lengths of constituents plus terminating zero plus slash */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync LogFunc(("path too long. caller=%s, path_len=%zu\n", caller, path_len));
e35e9d6317da2985728e7510bea9337b9893b66evboxsync shflstring_len = offsetof (SHFLSTRING, String.utf8) + path_len;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync LogRelFunc(("kmalloc failed, caller=%s\n", caller));
e35e9d6317da2985728e7510bea9337b9893b66evboxsync/* [dentry] contains string encoded in coding system that corresponds
e35e9d6317da2985728e7510bea9337b9893b66evboxsync to [sf_g]->nls, we must convert it to UTF8 here and pass down to
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync [sf_make_path] which will allocate SHFLSTRING and fill it in */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncsf_path_from_dentry (const char *caller, struct sf_glob_info *sf_g,
e35e9d6317da2985728e7510bea9337b9893b66evboxsync const char *d_name;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync const char *name;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync const char *in;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync for (i = 0; i < d_len; ++i) {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync /* We renamed the linux kernel wchar_t type to linux_wchar_t in
e35e9d6317da2985728e7510bea9337b9893b66evboxsync the-linux-kernel.h, as it conflicts with the C++ type of that name. */
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync err = sf_make_path (caller, sf_i, name, len, result);
50c3ee6cc6a9f816790595907558b355769f9c44vboxsync const char *in;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync nb = sf_g->nls->uni2char (uni, out, out_bound_len);
8b2f1e9e24bf9cb4340412463a0e75c4e0b035a6vboxsyncstatic struct sf_dir_buf *
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync LogRelFunc(("could not alloc directory buffer\n"));
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync LogRelFunc(("could not alloc directory buffer storage\n"));
e35e9d6317da2985728e7510bea9337b9893b66evboxsyncstatic struct sf_dir_buf *
e35e9d6317da2985728e7510bea9337b9893b66evboxsync if (b->free_bytes > 0) {
2fd917a77df587742609eaa229c7cf4922458ae8vboxsyncsf_dir_read_all (struct sf_glob_info *sf_g, struct sf_inode_info *sf_i,
e35e9d6317da2985728e7510bea9337b9893b66evboxsync err = sf_make_path (__func__, sf_i, "*", 1, &mask);
5c41f17e15c70a02e57fd39155f6394ebd9add66vboxsync LogRelFunc(("could not alloc directory buffer\n"));
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync /* fallthrough */
8952a4a0ea65bcb9926a1da734c1828baff52f54vboxsyncint sf_get_volume_info(struct super_block *sb, STRUCT_STATFS *stat)
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync rc = vboxCallFSInfo(&client_handle, &sf_g->map, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME,
c792fe5d6a56055c4d060db36316c4dac5311c7evboxsync stat->f_type = NFS_SUPER_MAGIC; /* XXX vboxsf type? */
36a0cf44771c76b56b4a6489136e3adf0343df0bvboxsync stat->f_bsize = SHFLVolumeInfo.ulBytesPerAllocationUnit;
36a0cf44771c76b56b4a6489136e3adf0343df0bvboxsync stat->f_blocks = SHFLVolumeInfo.ullTotalAllocationBytes
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync stat->f_bfree = SHFLVolumeInfo.ullAvailableAllocationBytes
36a0cf44771c76b56b4a6489136e3adf0343df0bvboxsync stat->f_bavail = SHFLVolumeInfo.ullAvailableAllocationBytes
c792fe5d6a56055c4d060db36316c4dac5311c7evboxsync stat->f_ffree = 1000; /* don't return 0 here since the guest may think
e35e9d6317da2985728e7510bea9337b9893b66evboxsync * that it is not possible to create any more files */