コード例 #1
0
ファイル: regops.c プロジェクト: svn2github/virtualbox
/**
 * Close a regular file.
 *
 * @param inode         the inode
 * @param file          the file
 * @returns 0 on success, Linux error code otherwise
 */
static int sf_reg_release(struct inode *inode, struct file *file)
{
    int rc;
    struct sf_reg_info *sf_r;
    struct sf_glob_info *sf_g;
    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);

    TRACE();
    sf_g = GET_GLOB_INFO(inode->i_sb);
    sf_r = file->private_data;

    BUG_ON(!sf_g);
    BUG_ON(!sf_r);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
    /* See the smbfs source (file.c). mmap in particular can cause data to be
     * written to the file after it is closed, which we can't cope with.  We
     * copy and paste the body of filemap_write_and_wait() here as it was not
     * defined before 2.6.6 and not exported until quite a bit later. */
    /* filemap_write_and_wait(inode->i_mapping); */
    if (   inode->i_mapping->nrpages
        && filemap_fdatawrite(inode->i_mapping) != -EIO)
        filemap_fdatawait(inode->i_mapping);
#endif
    rc = VbglR0SfClose(&client_handle, &sf_g->map, sf_r->handle);
    if (RT_FAILURE(rc))
        LogFunc(("VbglR0SfClose failed rc=%Rrc\n", rc));

    kfree(sf_r);
    sf_i->file = NULL;
    sf_i->handle = SHFL_HANDLE_NIL;
    file->private_data = NULL;
    return 0;
}
コード例 #2
0
ファイル: utils.c プロジェクト: bhanug/virtualbox
int sf_setattr(struct dentry *dentry, struct iattr *iattr)
{
    struct sf_glob_info *sf_g;
    struct sf_inode_info *sf_i;
    SHFLCREATEPARMS params;
    SHFLFSOBJINFO info;
    uint32_t cbBuffer;
    int rc, err;

    TRACE();

    sf_g = GET_GLOB_INFO(dentry->d_inode->i_sb);
    sf_i = GET_INODE_INFO(dentry->d_inode);
    err  = 0;

    RT_ZERO(params);
    params.Handle = SHFL_HANDLE_NIL;
    params.CreateFlags = SHFL_CF_ACT_OPEN_IF_EXISTS
                       | SHFL_CF_ACT_FAIL_IF_NEW
                       | SHFL_CF_ACCESS_ATTR_WRITE;

    /* this is at least required for Posix hosts */
    if (iattr->ia_valid & ATTR_SIZE)
        params.CreateFlags |= SHFL_CF_ACCESS_WRITE;

    rc = VbglR0SfCreate(&client_handle, &sf_g->map, sf_i->path, &params);
    if (RT_FAILURE(rc))
    {
        LogFunc(("VbglR0SfCreate(%s) failed rc=%Rrc\n",
                 sf_i->path->String.utf8, rc));
        err = -RTErrConvertToErrno(rc);
        goto fail2;
    }
    if (params.Result != SHFL_FILE_EXISTS)
    {
        LogFunc(("file %s does not exist\n", sf_i->path->String.utf8));
        err = -ENOENT;
        goto fail1;
    }

    /* Setting the file size and setting the other attributes has to be
     * handled separately, see implementation of vbsfSetFSInfo() in
     * vbsf.cpp */
    if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME))
    {
#define mode_set(r) ((iattr->ia_mode & (S_##r)) ? RTFS_UNIX_##r : 0)

        RT_ZERO(info);
        if (iattr->ia_valid & ATTR_MODE)
        {
            info.Attr.fMode  = mode_set(ISUID);
            info.Attr.fMode |= mode_set(ISGID);
            info.Attr.fMode |= mode_set(IRUSR);
            info.Attr.fMode |= mode_set(IWUSR);
            info.Attr.fMode |= mode_set(IXUSR);
            info.Attr.fMode |= mode_set(IRGRP);
            info.Attr.fMode |= mode_set(IWGRP);
            info.Attr.fMode |= mode_set(IXGRP);
            info.Attr.fMode |= mode_set(IROTH);
            info.Attr.fMode |= mode_set(IWOTH);
            info.Attr.fMode |= mode_set(IXOTH);

            if (iattr->ia_mode & S_IFDIR)
                info.Attr.fMode |= RTFS_TYPE_DIRECTORY;
            else
                info.Attr.fMode |= RTFS_TYPE_FILE;
        }

        if (iattr->ia_valid & ATTR_ATIME)
            sf_timespec_from_ftime(&info.AccessTime, &iattr->ia_atime);
        if (iattr->ia_valid & ATTR_MTIME)
            sf_timespec_from_ftime(&info.ModificationTime, &iattr->ia_mtime);
        /* ignore ctime (inode change time) as it can't be set from userland anyway */

        cbBuffer = sizeof(info);
        rc = VbglR0SfFsInfo(&client_handle, &sf_g->map, params.Handle,
                            SHFL_INFO_SET | SHFL_INFO_FILE, &cbBuffer,
                            (PSHFLDIRINFO)&info);
        if (RT_FAILURE(rc))
        {
            LogFunc(("VbglR0SfFsInfo(%s, FILE) failed rc=%Rrc\n",
                        sf_i->path->String.utf8, rc));
            err = -RTErrConvertToErrno(rc);
            goto fail1;
        }
    }

    if (iattr->ia_valid & ATTR_SIZE)
    {
        RT_ZERO(info);
        info.cbObject = iattr->ia_size;
        cbBuffer = sizeof(info);
        rc = VbglR0SfFsInfo(&client_handle, &sf_g->map, params.Handle,
                            SHFL_INFO_SET | SHFL_INFO_SIZE, &cbBuffer,
                            (PSHFLDIRINFO)&info);
        if (RT_FAILURE(rc))
        {
            LogFunc(("VbglR0SfFsInfo(%s, SIZE) failed rc=%Rrc\n",
                        sf_i->path->String.utf8, rc));
            err = -RTErrConvertToErrno(rc);
            goto fail1;
        }
    }

    rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle);
    if (RT_FAILURE(rc))
        LogFunc(("VbglR0SfClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc));

    return sf_inode_revalidate(dentry);

fail1:
    rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle);
    if (RT_FAILURE(rc))
        LogFunc(("VbglR0SfClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc));

fail2:
    return err;
}
コード例 #3
0
/**
 * Release VBoxVFS object handle openned by vboxvfs_open_internal().
 *
 * @param pMount   Mount session data.
 * @param pHandle           Handle to close.
 *
 * @return 0 on success, IPRT error code otherwise.
 */
int
vboxvfs_close_internal(vboxvfs_mount_t *pMount, SHFLHANDLE pHandle)
{
    AssertReturn(pMount, EINVAL);
    return VbglR0SfClose(&g_vboxSFClient, &pMount->pMap, pHandle);
}
コード例 #4
0
ファイル: dirops.c プロジェクト: bhanug/virtualbox
/**
 * Create a new regular file / directory.
 *
 * @param parent        inode of the directory
 * @param dentry        directory cache entry
 * @param mode          file mode
 * @param fDirectory    true if directory, false otherwise
 * @returns 0 on success, Linux error code otherwise
 */
static int sf_create_aux(struct inode *parent, struct dentry *dentry,
                         umode_t mode, int fDirectory)
{
    int rc, err;
    SHFLCREATEPARMS params;
    SHFLSTRING *path;
    struct sf_inode_info *sf_i = GET_INODE_INFO(parent);
    struct sf_glob_info *sf_g = GET_GLOB_INFO(parent->i_sb);

    TRACE();
    BUG_ON(!sf_i);
    BUG_ON(!sf_g);

    err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path);
    if (err)
        goto fail0;

    RT_ZERO(params);
    params.Handle = SHFL_HANDLE_NIL;
    params.CreateFlags = 0
                       | SHFL_CF_ACT_CREATE_IF_NEW
                       | SHFL_CF_ACT_FAIL_IF_EXISTS
                       | SHFL_CF_ACCESS_READWRITE
                       | (fDirectory ? SHFL_CF_DIRECTORY : 0)
                       ;
    params.Info.Attr.fMode = 0
                           | (fDirectory ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE)
                           | (mode & S_IRWXUGO)
                           ;
    params.Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;

    LogFunc(("sf_create_aux: calling VbglR0SfCreate, folder %s, flags %#x\n",
              path->String.utf8, params.CreateFlags));
    rc = VbglR0SfCreate(&client_handle, &sf_g->map, path, &params);
    if (RT_FAILURE(rc))
    {
        if (rc == VERR_WRITE_PROTECT)
        {
            err = -EROFS;
            goto fail1;
        }
        err = -EPROTO;
        LogFunc(("(%d): VbglR0SfCreate(%s) failed rc=%Rrc\n",
                    fDirectory, sf_i->path->String.utf8, rc));
        goto fail1;
    }

    if (params.Result != SHFL_FILE_CREATED)
    {
        err = -EPERM;
        LogFunc(("(%d): could not create file %s result=%d\n",
                    fDirectory, sf_i->path->String.utf8, params.Result));
        goto fail1;
    }

    err = sf_instantiate(parent, dentry, path, &params.Info,
                         fDirectory ? SHFL_HANDLE_NIL : params.Handle);
    if (err)
    {
        LogFunc(("(%d): could not instantiate dentry for %s err=%d\n",
                    fDirectory, sf_i->path->String.utf8, err));
        goto fail2;
    }

    /*
     * Don't close this handle right now. We assume that the same file is
     * opened with sf_reg_open() and later closed with sf_reg_close(). Save
     * the handle in between. Does not apply to directories. True?
     */
    if (fDirectory)
    {
        rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle);
        if (RT_FAILURE(rc))
            LogFunc(("(%d): VbglR0SfClose failed rc=%Rrc\n", fDirectory, rc));
    }

    sf_i->force_restat = 1;
    return 0;

fail2:
    rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle);
    if (RT_FAILURE(rc))
        LogFunc(("(%d): VbglR0SfClose failed rc=%Rrc\n", fDirectory, rc));

fail1:
    kfree(path);

fail0:
    return err;
}
コード例 #5
0
ファイル: dirops.c プロジェクト: bhanug/virtualbox
/**
 * Open a directory. Read the complete content into a buffer.
 *
 * @param inode     inode
 * @param file      file
 * @returns 0 on success, Linux error code otherwise
 */
static int sf_dir_open(struct inode *inode, struct file *file)
{
    int rc;
    int err;
    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
    struct sf_dir_info *sf_d;
    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
    SHFLCREATEPARMS params;

    TRACE();
    BUG_ON(!sf_g);
    BUG_ON(!sf_i);

    if (file->private_data)
    {
        LogFunc(("sf_dir_open() called on already opened directory '%s'\n",
                sf_i->path->String.utf8));
        return 0;
    }

    sf_d = sf_dir_info_alloc();
    if (!sf_d)
    {
        LogRelFunc(("could not allocate directory info for '%s'\n",
                    sf_i->path->String.utf8));
        return -ENOMEM;
    }

    RT_ZERO(params);
    params.Handle = SHFL_HANDLE_NIL;
    params.CreateFlags = 0
                       | SHFL_CF_DIRECTORY
                       | SHFL_CF_ACT_OPEN_IF_EXISTS
                       | SHFL_CF_ACT_FAIL_IF_NEW
                       | SHFL_CF_ACCESS_READ
                       ;

    LogFunc(("sf_dir_open(): calling VbglR0SfCreate, folder %s, flags %#x\n",
             sf_i->path->String.utf8, params.CreateFlags));
    rc = VbglR0SfCreate(&client_handle, &sf_g->map, sf_i->path, &params);
    if (RT_SUCCESS(rc))
    {
        if (params.Result == SHFL_FILE_EXISTS)
        {
            err = sf_dir_read_all(sf_g, sf_i, sf_d, params.Handle);
            if (!err)
                file->private_data = sf_d;
        }
        else
            err = -ENOENT;

        rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle);
        if (RT_FAILURE(rc))
            LogFunc(("sf_dir_open(): VbglR0SfClose(%s) after err=%d failed rc=%Rrc\n",
                     sf_i->path->String.utf8, err, rc));
    }
    else
        err = -EPERM;

    if (err)
        sf_dir_info_free(sf_d);

    return err;
}
コード例 #6
0
ファイル: dirops.c プロジェクト: bhanug/virtualbox
/**
 * Extract element ([dir]->f_pos) from the directory [dir] into [d_name].
 *
 * @returns 0 for success, 1 for end reached, Linux error code otherwise.
 */
static int sf_getdent(struct file *dir, char d_name[NAME_MAX], int *d_type)
{
    loff_t cur;
    struct sf_glob_info *sf_g;
    struct sf_dir_info *sf_d;
    struct sf_inode_info *sf_i;
    struct inode *inode;
    struct list_head *pos, *list;

    TRACE();

    inode = GET_F_DENTRY(dir)->d_inode;
    sf_i = GET_INODE_INFO(inode);
    sf_g = GET_GLOB_INFO(inode->i_sb);
    sf_d = dir->private_data;

    BUG_ON(!sf_g);
    BUG_ON(!sf_d);
    BUG_ON(!sf_i);

    if (sf_i->force_reread)
    {
        int rc;
        int err;
        SHFLCREATEPARMS params;

        RT_ZERO(params);
        params.Handle = SHFL_HANDLE_NIL;
        params.CreateFlags = 0
                           | SHFL_CF_DIRECTORY
                           | SHFL_CF_ACT_OPEN_IF_EXISTS
                           | SHFL_CF_ACT_FAIL_IF_NEW
                           | SHFL_CF_ACCESS_READ
                           ;

        LogFunc(("sf_getdent: calling VbglR0SfCreate, folder %s, flags %#x\n",
                  sf_i->path->String.utf8, params.CreateFlags));
        rc = VbglR0SfCreate(&client_handle, &sf_g->map, sf_i->path, &params);
        if (RT_FAILURE(rc))
        {
            LogFunc(("VbglR0SfCreate(%s) failed rc=%Rrc\n",
                        sf_i->path->String.utf8, rc));
            return -EPERM;
        }

        if (params.Result != SHFL_FILE_EXISTS)
        {
            LogFunc(("directory %s does not exist\n", sf_i->path->String.utf8));
            sf_dir_info_free(sf_d);
            return -ENOENT;
        }

        sf_dir_info_empty(sf_d);
        err = sf_dir_read_all(sf_g, sf_i, sf_d, params.Handle);
        rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle);
        if (RT_FAILURE(rc))
            LogFunc(("VbglR0SfClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc));
        if (err)
            return err;

        sf_i->force_reread = 0;
    }

    cur = 0;
    list = &sf_d->info_list;
    list_for_each(pos, list)
    {
        struct sf_dir_buf *b;
        SHFLDIRINFO *info;
        loff_t i;

        b = list_entry(pos, struct sf_dir_buf, head);
        if (dir->f_pos >= cur + b->cEntries)
        {
            cur += b->cEntries;
            continue;
        }

        for (i = 0, info = b->buf; i < dir->f_pos - cur; ++i)
        {
            size_t size;

            size = offsetof(SHFLDIRINFO, name.String) + info->name.u16Size;
            info = (SHFLDIRINFO *) ((uintptr_t) info + size);
        }

        *d_type = sf_get_d_type(info->Info.Attr.fMode);

        return sf_nlscpy(sf_g, d_name, NAME_MAX,
                         info->name.String.utf8, info->name.u16Length);
    }

    return 1;
}