utils.c revision aa9eecc1b20f1a9d5ef527d054af454a08879a9d
e35e9d6317da2985728e7510bea9337b9893b66evboxsync/** @file
e35e9d6317da2985728e7510bea9337b9893b66evboxsync *
e35e9d6317da2985728e7510bea9337b9893b66evboxsync * vboxvfs -- VirtualBox Guest Additions for Linux:
e35e9d6317da2985728e7510bea9337b9893b66evboxsync * Utility functions.
e35e9d6317da2985728e7510bea9337b9893b66evboxsync * Mainly conversion from/to VirtualBox/Linux data structures
e35e9d6317da2985728e7510bea9337b9893b66evboxsync */
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync/*
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync *
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.
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync *
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.
e35e9d6317da2985728e7510bea9337b9893b66evboxsync */
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync#include "vfsmod.h"
e35e9d6317da2985728e7510bea9337b9893b66evboxsync#include <linux/nfs_fs.h>
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync#include <linux/vfs.h>
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
08122b11035de1e54ce1e665dff7260fc548db72vboxsync/* #define USE_VMALLOC */
08122b11035de1e54ce1e665dff7260fc548db72vboxsync
b5b8f3d0d95893edd81062c1b5d0bc455cc79bc1vboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 0)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync/*
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 *
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * http://us1.samba.org/samba/ftp/cifs-cvs/ols2006-fs-tutorial-smf.odp
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync *
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * and the sample implementation
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync *
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync * http://pserver.samba.org/samba/ftp/cifs-cvs/samplefs.tar.gz
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncstatic struct backing_dev_info sf_backing_dev_info = {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync .ra_pages = 0, /* No readahead */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync# if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 12)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync .capabilities = BDI_CAP_MAP_DIRECT /* MAP_SHARED */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync | BDI_CAP_MAP_COPY /* MAP_PRIVATE */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync | BDI_CAP_READ_MAP /* can be mapped for reading */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync | BDI_CAP_WRITE_MAP /* can be mapped for writing */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync | BDI_CAP_EXEC_MAP, /* can be mapped for execution */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync# endif
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync};
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 0) */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 0)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncstatic void
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncsf_ftime_from_timespec (time_t *time, RTTIMESPEC *ts)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync{
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync int64_t t = RTTimeSpecGetNano (ts);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync do_div (t, 1000000000);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync *time = t;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync}
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync#else
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncstatic void
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncsf_ftime_from_timespec (struct timespec *tv, RTTIMESPEC *ts)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync{
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync int64_t t = RTTimeSpecGetNano (ts);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync int64_t nsec;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync nsec = do_div (t, 1000000000);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync tv->tv_sec = t;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync tv->tv_nsec = nsec;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync}
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync#endif
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync/* set [inode] attributes based on [info], uid/gid based on [sf_g] */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncvoid
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncsf_init_inode (struct sf_glob_info *sf_g, struct inode *inode,
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync RTFSOBJINFO *info)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync{
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync int is_dir;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync RTFSOBJATTR *attr;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync int mode;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync TRACE ();
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync attr = &info->Attr;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync is_dir = RTFS_IS_DIRECTORY (attr->fMode);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync#define mode_set(r) attr->fMode & (RTFS_UNIX_##r) ? (S_##r) : 0;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync mode = mode_set (ISUID);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync mode |= mode_set (ISGID);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync mode |= mode_set (IRUSR);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync mode |= mode_set (IWUSR);
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync mode |= mode_set (IXUSR);
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync
08122b11035de1e54ce1e665dff7260fc548db72vboxsync mode |= mode_set (IRGRP);
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync mode |= mode_set (IWGRP);
2561352ae77d8f2f825526a6cbafa34b45f16972vboxsync mode |= mode_set (IXGRP);
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync
6eb6707c9fc46c66988caf4b4224b874985d9c2dvboxsync mode |= mode_set (IROTH);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync mode |= mode_set (IWOTH);
08122b11035de1e54ce1e665dff7260fc548db72vboxsync mode |= mode_set (IXOTH);
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync#undef mode_set
b5b8f3d0d95893edd81062c1b5d0bc455cc79bc1vboxsync
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 0)
6eb6707c9fc46c66988caf4b4224b874985d9c2dvboxsync inode->i_mapping->a_ops = &sf_reg_aops;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync inode->i_mapping->backing_dev_info = &sf_backing_dev_info;
08122b11035de1e54ce1e665dff7260fc548db72vboxsync#endif
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync if (is_dir) {
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync inode->i_mode = sf_g->dmode != ~0 ? (sf_g->dmode & 0777) : mode;
08122b11035de1e54ce1e665dff7260fc548db72vboxsync inode->i_mode &= ~sf_g->dmask;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync inode->i_mode |= S_IFDIR;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync inode->i_op = &sf_dir_iops;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync inode->i_fop = &sf_dir_fops;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync /* XXX: this probably should be set to the number of entries
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync in the directory plus two (. ..) */
c65e2fedaf400b449a85ae6db7b84858f2613708vboxsync inode->i_nlink = 1;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync else {
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync inode->i_mode = sf_g->fmode != ~0 ? (sf_g->fmode & 0x777): mode;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync inode->i_mode &= ~sf_g->fmask;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync inode->i_mode |= S_IFREG;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync inode->i_op = &sf_reg_iops;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync inode->i_fop = &sf_reg_fops;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync inode->i_nlink = 1;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync }
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync inode->i_uid = sf_g->uid;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync inode->i_gid = sf_g->gid;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync inode->i_size = info->cbObject;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 19) && !defined(KERNEL_FC6)
aaa80e9df329609078dea844a11f2611443b677avboxsync inode->i_blksize = 4096;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync#endif
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 4, 11)
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync inode->i_blkbits = 12;
aaa80e9df329609078dea844a11f2611443b677avboxsync#endif
08e715a5fb97536a462b199124a0c6e925cfa76cvboxsync inode->i_blocks = (info->cbObject + 4095) / 4096;
aaa80e9df329609078dea844a11f2611443b677avboxsync
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);
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync}
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsyncint
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsyncsf_stat (const char *caller, struct sf_glob_info *sf_g,
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync SHFLSTRING *path, RTFSOBJINFO *result, int ok_to_fail)
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync{
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync int rc;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync SHFLCREATEPARMS params;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync TRACE ();
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync params.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync LogFunc(("calling vboxCallCreate, file %s, flags %#x\n",
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync path->String.utf8, params.CreateFlags));
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync rc = vboxCallCreate (&client_handle, &sf_g->map, path, &params);
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync if (VBOX_FAILURE (rc)) {
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync LogFunc(("vboxCallCreate(%s) failed. caller=%s, rc=%Vrc\n",
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync path->String.utf8, rc, caller));
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync return -EPROTO;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync }
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync if (params.Result != SHFL_FILE_EXISTS) {
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync if (!ok_to_fail) {
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync LogFunc(("vboxCallCreate(%s) file does not exist. caller=%s, result=%d\n",
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync path->String.utf8, params.Result, caller));
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync }
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync return -ENOENT;
8b2f1e9e24bf9cb4340412463a0e75c4e0b035a6vboxsync }
aaa80e9df329609078dea844a11f2611443b677avboxsync
aaa80e9df329609078dea844a11f2611443b677avboxsync *result = params.Info;
a7f701e8c51193f7c21137cc173ea5f86e53cac2vboxsync return 0;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync}
a7f701e8c51193f7c21137cc173ea5f86e53cac2vboxsync
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 */
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsyncint
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsyncsf_inode_revalidate (struct dentry *dentry)
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync{
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync int err;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync struct sf_glob_info *sf_g;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync struct sf_inode_info *sf_i;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync RTFSOBJINFO info;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync TRACE ();
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync if (!dentry || !dentry->d_inode) {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync LogFunc(("no dentry(%p) or inode(%p)\n", dentry, dentry->d_inode));
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync return -EINVAL;
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync }
c2e62d39261f9f69ab4e14b2bbd986bf1b1faaf9vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync sf_g = GET_GLOB_INFO (dentry->d_inode->i_sb);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync sf_i = GET_INODE_INFO (dentry->d_inode);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync#if 0
5cb8545771849c97101a5ee9bb57d0fdac922c44vboxsync printk ("%s called by %p:%p\n",
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync sf_i->path->String.utf8,
5cb8545771849c97101a5ee9bb57d0fdac922c44vboxsync __builtin_return_address (0),
e35e9d6317da2985728e7510bea9337b9893b66evboxsync __builtin_return_address (1));
e35e9d6317da2985728e7510bea9337b9893b66evboxsync#endif
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync BUG_ON (!sf_g);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync BUG_ON (!sf_i);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync if (!sf_i->force_restat) {
8b2f1e9e24bf9cb4340412463a0e75c4e0b035a6vboxsync if (jiffies - dentry->d_time < sf_g->ttl) {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync return 0;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync }
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync }
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync err = sf_stat (__func__, sf_g, sf_i->path, &info, 1);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync if (err) {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync return err;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync }
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync dentry->d_time = jiffies;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync sf_init_inode (sf_g, dentry->d_inode, &info);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync return 0;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync}
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
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] */
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsyncstatic int
5cb8545771849c97101a5ee9bb57d0fdac922c44vboxsync#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 0)
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsyncsf_dentry_revalidate (struct dentry *dentry, int flags)
5cb8545771849c97101a5ee9bb57d0fdac922c44vboxsync#else
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync sf_dentry_revalidate (struct dentry *dentry, struct nameidata *nd)
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync#endif
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync{
5cb8545771849c97101a5ee9bb57d0fdac922c44vboxsync TRACE ();
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync if (sf_inode_revalidate (dentry)) {
5cb8545771849c97101a5ee9bb57d0fdac922c44vboxsync return 0;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync return 1;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync}
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
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] */
e35e9d6317da2985728e7510bea9337b9893b66evboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 0)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncint
e35e9d6317da2985728e7510bea9337b9893b66evboxsyncsf_getattr (struct vfsmount *mnt, struct dentry *dentry, struct kstat *kstat)
e35e9d6317da2985728e7510bea9337b9893b66evboxsync{
e35e9d6317da2985728e7510bea9337b9893b66evboxsync int err;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync TRACE ();
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync err = sf_inode_revalidate (dentry);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync if (err) {
e35e9d6317da2985728e7510bea9337b9893b66evboxsync return err;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync generic_fillattr (dentry->d_inode, kstat);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync return 0;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync}
e35e9d6317da2985728e7510bea9337b9893b66evboxsync#endif
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsyncstatic int
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncsf_make_path (const char *caller, struct sf_inode_info *sf_i,
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync const char *d_name, size_t d_len, SHFLSTRING **result)
e35e9d6317da2985728e7510bea9337b9893b66evboxsync{
e35e9d6317da2985728e7510bea9337b9893b66evboxsync size_t path_len, shflstring_len;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync SHFLSTRING *tmp;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync uint16_t p_len;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync uint8_t *p_name;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync uint8_t *dst;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync int is_root = 0;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync TRACE ();
e35e9d6317da2985728e7510bea9337b9893b66evboxsync p_len = sf_i->path->u16Length;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync p_name = sf_i->path->String.utf8;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync if (p_len == 1 && *p_name == '/') {
e35e9d6317da2985728e7510bea9337b9893b66evboxsync path_len = d_len + 1;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync is_root = 1;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync else {
e35e9d6317da2985728e7510bea9337b9893b66evboxsync /* lengths of constituents plus terminating zero plus slash */
e35e9d6317da2985728e7510bea9337b9893b66evboxsync path_len = p_len + d_len + 2;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync if (path_len > 0xffff) {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync LogFunc(("path too long. caller=%s, path_len=%zu\n", caller, path_len));
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync return -ENAMETOOLONG;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync shflstring_len = offsetof (SHFLSTRING, String.utf8) + path_len;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync tmp = kmalloc (shflstring_len, GFP_KERNEL);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync if (!tmp) {
e35e9d6317da2985728e7510bea9337b9893b66evboxsync LogRelFunc(("kmalloc failed, caller=%s\n", caller));
e35e9d6317da2985728e7510bea9337b9893b66evboxsync return -ENOMEM;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync tmp->u16Length = path_len - 1;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync tmp->u16Size = path_len;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync if (is_root) {
e35e9d6317da2985728e7510bea9337b9893b66evboxsync memcpy (tmp->String.utf8, d_name, d_len + 1);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync else {
e35e9d6317da2985728e7510bea9337b9893b66evboxsync dst = tmp->String.utf8;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync memcpy (dst, p_name, p_len);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync dst += p_len; *dst++ = '/';
e35e9d6317da2985728e7510bea9337b9893b66evboxsync memcpy (dst, d_name, d_len);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync dst[d_len] = 0;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync *result = tmp;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync return 0;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync}
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
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 */
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncint
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncsf_path_from_dentry (const char *caller, struct sf_glob_info *sf_g,
e35e9d6317da2985728e7510bea9337b9893b66evboxsync struct sf_inode_info *sf_i, struct dentry *dentry,
e35e9d6317da2985728e7510bea9337b9893b66evboxsync SHFLSTRING **result)
e35e9d6317da2985728e7510bea9337b9893b66evboxsync{
e35e9d6317da2985728e7510bea9337b9893b66evboxsync int err;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync const char *d_name;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync size_t d_len;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync const char *name;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync size_t len = 0;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync TRACE ();
e35e9d6317da2985728e7510bea9337b9893b66evboxsync d_name = dentry->d_name.name;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync d_len = dentry->d_name.len;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync if (sf_g->nls) {
e35e9d6317da2985728e7510bea9337b9893b66evboxsync size_t in_len, i, out_bound_len;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync const char *in;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync char *out;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync in = d_name;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync in_len = d_len;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync out_bound_len = PATH_MAX;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync out = kmalloc (out_bound_len, GFP_KERNEL);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync name = out;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
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. */
e35e9d6317da2985728e7510bea9337b9893b66evboxsync linux_wchar_t uni;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync int nb;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync nb = sf_g->nls->char2uni (in, in_len, &uni);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync if (nb < 0) {
e35e9d6317da2985728e7510bea9337b9893b66evboxsync LogFunc(("nls->char2uni failed %x %d\n",
e35e9d6317da2985728e7510bea9337b9893b66evboxsync *in, in_len));
e35e9d6317da2985728e7510bea9337b9893b66evboxsync err = -EINVAL;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync goto fail1;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync in_len -= nb;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync in += nb;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync nb = utf8_wctomb (out, uni, out_bound_len);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync if (nb < 0) {
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync LogFunc(("nls->uni2char failed %x %d\n",
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync uni, out_bound_len));
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync err = -EINVAL;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync goto fail1;
50c3ee6cc6a9f816790595907558b355769f9c44vboxsync }
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync out_bound_len -= nb;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync out += nb;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync len += nb;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync }
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync if (len >= PATH_MAX - 1) {
50c3ee6cc6a9f816790595907558b355769f9c44vboxsync err = -ENAMETOOLONG;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync goto fail1;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync }
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync LogFunc(("result(%d) = %.*s\n", len, len, name));
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync *out = 0;
50c3ee6cc6a9f816790595907558b355769f9c44vboxsync }
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync else {
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync name = d_name;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync len = d_len;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync }
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync err = sf_make_path (caller, sf_i, name, len, result);
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync if (name != d_name) {
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync kfree (name);
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync }
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync return err;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync fail1:
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync kfree (name);
50c3ee6cc6a9f816790595907558b355769f9c44vboxsync return err;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync}
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync
50c3ee6cc6a9f816790595907558b355769f9c44vboxsyncint
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncsf_nlscpy (struct sf_glob_info *sf_g,
50c3ee6cc6a9f816790595907558b355769f9c44vboxsync char *name, size_t name_bound_len,
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync const unsigned char *utf8_name, size_t utf8_len)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync{
50c3ee6cc6a9f816790595907558b355769f9c44vboxsync if (sf_g->nls) {
50c3ee6cc6a9f816790595907558b355769f9c44vboxsync const char *in;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync char *out;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync size_t out_len;
50c3ee6cc6a9f816790595907558b355769f9c44vboxsync size_t out_bound_len;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync size_t in_bound_len;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync in = utf8_name;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync in_bound_len = utf8_len;
50c3ee6cc6a9f816790595907558b355769f9c44vboxsync
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync out = name;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync out_len = 0;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync out_bound_len = name_bound_len;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync while (in_bound_len) {
50c3ee6cc6a9f816790595907558b355769f9c44vboxsync int nb;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync wchar_t uni;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync nb = utf8_mbtowc (&uni, in, in_bound_len);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync if (nb < 0) {
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync LogFunc(("utf8_mbtowc failed(%s) %x:%d\n",
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync (const char *) utf8_name, *in, in_bound_len));
50c3ee6cc6a9f816790595907558b355769f9c44vboxsync return -EINVAL;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync }
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync in += nb;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync in_bound_len -= nb;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync nb = sf_g->nls->uni2char (uni, out, out_bound_len);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync if (nb < 0) {
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync LogFunc(("nls->uni2char failed(%s) %x:%d\n",
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync utf8_name, uni, out_bound_len));
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync return nb;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync out += nb;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync out_bound_len -= nb;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync out_len += nb;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync *out = 0;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync return 0;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync else {
e35e9d6317da2985728e7510bea9337b9893b66evboxsync if (utf8_len + 1 > name_bound_len) {
e35e9d6317da2985728e7510bea9337b9893b66evboxsync return -ENAMETOOLONG;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync }
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync else {
e35e9d6317da2985728e7510bea9337b9893b66evboxsync memcpy (name, utf8_name, utf8_len + 1);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync return 0;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync }
e35e9d6317da2985728e7510bea9337b9893b66evboxsync}
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
8b2f1e9e24bf9cb4340412463a0e75c4e0b035a6vboxsyncstatic struct sf_dir_buf *
e35e9d6317da2985728e7510bea9337b9893b66evboxsyncsf_dir_buf_alloc (void)
e35e9d6317da2985728e7510bea9337b9893b66evboxsync{
e35e9d6317da2985728e7510bea9337b9893b66evboxsync struct sf_dir_buf *b;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync TRACE ();
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync b = kmalloc (sizeof (*b), GFP_KERNEL);
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync if (!b) {
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync LogRelFunc(("could not alloc directory buffer\n"));
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync return NULL;
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync }
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync#ifdef USE_VMALLOC
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync b->buf = vmalloc (16384);
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync#else
e35e9d6317da2985728e7510bea9337b9893b66evboxsync b->buf = kmalloc (16384, GFP_KERNEL);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync#endif
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync if (!b->buf) {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync kfree (b);
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync LogRelFunc(("could not alloc directory buffer storage\n"));
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync return NULL;
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync }
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync INIT_LIST_HEAD (&b->head);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync b->nb_entries = 0;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync b->used_bytes = 0;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync b->free_bytes = 16384;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync return b;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync}
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncstatic void
e35e9d6317da2985728e7510bea9337b9893b66evboxsyncsf_dir_buf_free (struct sf_dir_buf *b)
e35e9d6317da2985728e7510bea9337b9893b66evboxsync{
e35e9d6317da2985728e7510bea9337b9893b66evboxsync BUG_ON (!b || !b->buf);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsync TRACE ();
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync list_del (&b->head);
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync#ifdef USE_VMALLOC
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync vfree (b->buf);
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync#else
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync kfree (b->buf);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync#endif
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync kfree (b);
e35e9d6317da2985728e7510bea9337b9893b66evboxsync}
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsyncvoid
08122b11035de1e54ce1e665dff7260fc548db72vboxsyncsf_dir_info_free (struct sf_dir_info *p)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync{
e35e9d6317da2985728e7510bea9337b9893b66evboxsync struct list_head *list, *pos, *tmp;
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync TRACE ();
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync list = &p->info_list;
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync list_for_each_safe (pos, tmp, list) {
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync struct sf_dir_buf *b;
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync b = list_entry (pos, struct sf_dir_buf, head);
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync sf_dir_buf_free (b);
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync }
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync kfree (p);
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync}
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync
3eef14636dd78f6e25610b89aec40879e657caf4vboxsyncstruct sf_dir_info *
3eef14636dd78f6e25610b89aec40879e657caf4vboxsyncsf_dir_info_alloc (void)
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync{
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync struct sf_dir_info *p;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync TRACE ();
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync p = kmalloc (sizeof (*p), GFP_KERNEL);
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync if (!p) {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync LogRelFunc(("could not alloc directory info\n"));
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync return NULL;
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync }
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync INIT_LIST_HEAD (&p->info_list);
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync return p;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync}
3eef14636dd78f6e25610b89aec40879e657caf4vboxsync
e35e9d6317da2985728e7510bea9337b9893b66evboxsyncstatic struct sf_dir_buf *
e35e9d6317da2985728e7510bea9337b9893b66evboxsyncsf_get_non_empty_dir_buf (struct sf_dir_info *sf_d)
da570ef57fe454ae2d9d5d88a7bfea214723dbb1vboxsync{
08122b11035de1e54ce1e665dff7260fc548db72vboxsync struct list_head *list, *pos;
1d96c25e994a2160c1697208bb398d79ca117c4avboxsync
08122b11035de1e54ce1e665dff7260fc548db72vboxsync list = &sf_d->info_list;
08122b11035de1e54ce1e665dff7260fc548db72vboxsync list_for_each (pos, list) {
1d96c25e994a2160c1697208bb398d79ca117c4avboxsync struct sf_dir_buf *b;
08122b11035de1e54ce1e665dff7260fc548db72vboxsync
2ea0ec406117609d51bd5ac51cbb3d4f0de9a16dvboxsync b = list_entry (pos, struct sf_dir_buf, head);
08122b11035de1e54ce1e665dff7260fc548db72vboxsync if (!b) {
08122b11035de1e54ce1e665dff7260fc548db72vboxsync return NULL;
08122b11035de1e54ce1e665dff7260fc548db72vboxsync }
08122b11035de1e54ce1e665dff7260fc548db72vboxsync else {
e35e9d6317da2985728e7510bea9337b9893b66evboxsync if (b->free_bytes > 0) {
e35e9d6317da2985728e7510bea9337b9893b66evboxsync return b;
08122b11035de1e54ce1e665dff7260fc548db72vboxsync }
2fd917a77df587742609eaa229c7cf4922458ae8vboxsync }
2fd917a77df587742609eaa229c7cf4922458ae8vboxsync }
1d27f9d208503988168cd9a8a902a0f48cf52a12vboxsync
2fd917a77df587742609eaa229c7cf4922458ae8vboxsync return NULL;
2fd917a77df587742609eaa229c7cf4922458ae8vboxsync}
2fd917a77df587742609eaa229c7cf4922458ae8vboxsync
2fd917a77df587742609eaa229c7cf4922458ae8vboxsyncint
2fd917a77df587742609eaa229c7cf4922458ae8vboxsyncsf_dir_read_all (struct sf_glob_info *sf_g, struct sf_inode_info *sf_i,
e35e9d6317da2985728e7510bea9337b9893b66evboxsync struct sf_dir_info *sf_d, SHFLHANDLE handle)
989c8375a95357db2bd39e0897fdcb218e749b30vboxsync{
989c8375a95357db2bd39e0897fdcb218e749b30vboxsync int err;
989c8375a95357db2bd39e0897fdcb218e749b30vboxsync SHFLSTRING *mask;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync struct sf_dir_buf *b;
989c8375a95357db2bd39e0897fdcb218e749b30vboxsync
5c41f17e15c70a02e57fd39155f6394ebd9add66vboxsync TRACE ();
e35e9d6317da2985728e7510bea9337b9893b66evboxsync err = sf_make_path (__func__, sf_i, "*", 1, &mask);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync if (err) {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync goto fail0;
b844a5645b69a09c4d6dacb9cfe96bb138cb21d4vboxsync }
b844a5645b69a09c4d6dacb9cfe96bb138cb21d4vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync b = sf_get_non_empty_dir_buf (sf_d);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync for (;;) {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync int rc;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync void *buf;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync uint32_t buf_size;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync uint32_t nb_ents;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync if (!b) {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync b = sf_dir_buf_alloc ();
5c41f17e15c70a02e57fd39155f6394ebd9add66vboxsync if (!b) {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync err = -ENOMEM;
5c41f17e15c70a02e57fd39155f6394ebd9add66vboxsync LogRelFunc(("could not alloc directory buffer\n"));
dafcc1aee6fa9a280e6c6d7630132e5a778f3a6fvboxsync goto fail1;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync }
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync }
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync list_add (&b->head, &sf_d->info_list);
5c41f17e15c70a02e57fd39155f6394ebd9add66vboxsync
5c41f17e15c70a02e57fd39155f6394ebd9add66vboxsync buf = b->buf;
c792fe5d6a56055c4d060db36316c4dac5311c7evboxsync buf_size = b->free_bytes;
36a0cf44771c76b56b4a6489136e3adf0343df0bvboxsync
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync rc = vboxCallDirInfo (
36a0cf44771c76b56b4a6489136e3adf0343df0bvboxsync &client_handle,
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync &sf_g->map,
a23d9b6011c292ab4d858fc7d83a2216843cd54evboxsync handle,
e9802cd9ee289e494f01f2c37e714911d120cd30vboxsync mask,
a23d9b6011c292ab4d858fc7d83a2216843cd54evboxsync 0,
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync 0,
e9802cd9ee289e494f01f2c37e714911d120cd30vboxsync &buf_size,
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync buf,
36a0cf44771c76b56b4a6489136e3adf0343df0bvboxsync &nb_ents
a23d9b6011c292ab4d858fc7d83a2216843cd54evboxsync );
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync switch (rc) {
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync case VINF_SUCCESS:
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync /* fallthrough */
ebb33f3aef3b410579a2865109426b798b9d4a9dvboxsync case VERR_NO_MORE_FILES:
e9802cd9ee289e494f01f2c37e714911d120cd30vboxsync break;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync
a23d9b6011c292ab4d858fc7d83a2216843cd54evboxsync case VERR_NO_TRANSLATION:
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync LogFunc(("host could not translate entry\n"));
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync /* XXX */
a23d9b6011c292ab4d858fc7d83a2216843cd54evboxsync break;
a23d9b6011c292ab4d858fc7d83a2216843cd54evboxsync
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync default:
a23d9b6011c292ab4d858fc7d83a2216843cd54evboxsync err = -RTErrConvertToErrno (rc);
36a0cf44771c76b56b4a6489136e3adf0343df0bvboxsync LogFunc(("vboxCallDirInfo failed rc=%Vrc\n", rc));
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync goto fail1;
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync }
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync b->nb_entries += nb_ents;
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync b->free_bytes -= buf_size;
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync b->used_bytes += buf_size;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync b = NULL;
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync if (VBOX_FAILURE (rc)) {
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync break;
c792fe5d6a56055c4d060db36316c4dac5311c7evboxsync }
619da14dbf1f40ada039a6ebceedec8a6abe7696vboxsync }
8952a4a0ea65bcb9926a1da734c1828baff52f54vboxsync return 0;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync
8952a4a0ea65bcb9926a1da734c1828baff52f54vboxsync fail1:
8952a4a0ea65bcb9926a1da734c1828baff52f54vboxsync kfree (mask);
8952a4a0ea65bcb9926a1da734c1828baff52f54vboxsync fail0:
8952a4a0ea65bcb9926a1da734c1828baff52f54vboxsync return err;
8952a4a0ea65bcb9926a1da734c1828baff52f54vboxsync}
8952a4a0ea65bcb9926a1da734c1828baff52f54vboxsync
8952a4a0ea65bcb9926a1da734c1828baff52f54vboxsyncint sf_get_volume_info(struct super_block *sb, STRUCT_STATFS *stat)
619da14dbf1f40ada039a6ebceedec8a6abe7696vboxsync{
619da14dbf1f40ada039a6ebceedec8a6abe7696vboxsync struct sf_glob_info *sf_g;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync SHFLVOLINFO SHFLVolumeInfo;
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync uint32_t cbBuffer;
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync int rc;
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync sf_g = GET_GLOB_INFO (sb);
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync cbBuffer = sizeof(SHFLVolumeInfo);
ee231a249824f0a96643fb8b705f5b6cf3617b46vboxsync rc = vboxCallFSInfo(&client_handle, &sf_g->map, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME,
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync &cbBuffer, (PSHFLDIRINFO)&SHFLVolumeInfo);
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync if (VBOX_FAILURE(rc))
619da14dbf1f40ada039a6ebceedec8a6abe7696vboxsync return -RTErrConvertToErrno(rc);
c792fe5d6a56055c4d060db36316c4dac5311c7evboxsync
c792fe5d6a56055c4d060db36316c4dac5311c7evboxsync stat->f_type = NFS_SUPER_MAGIC; /* XXX vboxsf type? */
36a0cf44771c76b56b4a6489136e3adf0343df0bvboxsync stat->f_bsize = SHFLVolumeInfo.ulBytesPerAllocationUnit;
36a0cf44771c76b56b4a6489136e3adf0343df0bvboxsync stat->f_blocks = SHFLVolumeInfo.ullTotalAllocationBytes
36a0cf44771c76b56b4a6489136e3adf0343df0bvboxsync / SHFLVolumeInfo.ulBytesPerAllocationUnit;
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync stat->f_bfree = SHFLVolumeInfo.ullAvailableAllocationBytes
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync / SHFLVolumeInfo.ulBytesPerAllocationUnit;
36a0cf44771c76b56b4a6489136e3adf0343df0bvboxsync stat->f_bavail = SHFLVolumeInfo.ullAvailableAllocationBytes
c792fe5d6a56055c4d060db36316c4dac5311c7evboxsync / SHFLVolumeInfo.ulBytesPerAllocationUnit;
c792fe5d6a56055c4d060db36316c4dac5311c7evboxsync stat->f_files = 1000;
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 */
ced49ddf2480e97120d7bb28cd774ab609047875vboxsync stat->f_fsid.val[0] = 0;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync stat->f_fsid.val[1] = 0;
e35e9d6317da2985728e7510bea9337b9893b66evboxsync stat->f_namelen = 255;
50c3ee6cc6a9f816790595907558b355769f9c44vboxsync return 0;
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync}
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsyncstruct dentry_operations sf_dentry_ops = {
a253309ecf51232be71a5c0f7b888e03f51906a3vboxsync .d_revalidate = sf_dentry_revalidate
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync};
15fe3cf8212d4ca73ea0a4fe547892bcddef6e16vboxsync