dirops.c revision 13fdd42f1fc3e519650037a920e6a54c24973866
/** @file
*
* vboxvfs -- VirtualBox Guest Additions for Linux:
* Directory inode and file operations
*/
/*
* Copyright (C) 2006 InnoTek Systemberatung GmbH
*
* 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 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.
*
* If you received this file as part of a commercial VirtualBox
* distribution, then only the terms of your commercial VirtualBox
* license agreement apply instead of the previous paragraph.
*/
static int
{
int rc;
int err;
struct sf_dir_info *sf_d;
TRACE ();
if (file->private_data) {
elog ("dir_open called on already opened directory %s\n",
return 0;
}
sf_d = sf_dir_info_alloc ();
if (!sf_d) {
elog ("could not allocate directory info for %s\n",
return -ENOMEM;
}
params.CreateFlags = 0
;
if (VBOX_FAILURE (rc)) {
elog ("vboxCallCreate(%s) failed rc=%d\n",
return -EPERM;
}
return -ENOENT;
}
if (err) {
if (VBOX_FAILURE (rc)) {
elog ("vboxCallClose(%s) after err=%d failed rc=%d\n",
}
return err;
}
if (VBOX_FAILURE (rc)) {
elog ("vboxCallClose(%s) failed rc=%d\n",
}
return 0;
}
/* This is called when reference count of [file] goes to zero. Notify
the host that it can free whatever is associated with this
directory and deallocate our own internal buffers */
static int
{
TRACE ();
if (file->private_data) {
}
return 0;
}
/* Extract element ([dir]->f_pos) from the directory [dir] into
[d_name], return:
0 all ok
1 end reached
-errno some form of error*/
int
{
struct sf_glob_info *sf_g;
struct sf_dir_info *sf_d;
TRACE ();
cur = 0;
struct sf_dir_buf *b;
loff_t i;
char *name_ptr;
cur += b->nb_entries;
continue;
}
}
}
return 1;
}
/* This is called when vfs wants to populate internal buffers with
directory [dir]s contents. [opaque] is an argument to the
[filldir]. [filldir] magically modifies it's argument - [opaque]
and takes following additional arguments (which i in turn get from
the host via sf_getdent):
name : name of the entry (i must also supply it's length huh?)
type : type of the entry (FILE | DIR | etc) (i ellect to use DT_UNKNOWN)
ino : inode number of the entry (i fake those)
[dir] contains:
f_pos : cursor into the directory listing
private_data : mean of communcation with the host side
Extract elements from the directory listing (incrementing f_pos
along the way) and feed them to [filldir] until:
a. there are no more entries (i.e. sf_getdent set done to 1)
b. failure to compute fake inode number
c. filldir returns an error (see comment on that) */
static int
{
TRACE ();
for (;;) {
int err;
switch (err) {
case 1:
return 0;
case 0:
break;
case -1:
default:
/* skip erroneous entry and proceed */
continue;
}
/* d_name now contains valid entry name */
elog2 ("can not compute ino\n");
return -EINVAL;
}
if (err) {
/* Rely on the fact that filldir returns error
only when it runs out of space in opaque */
return 0;
}
}
BUG ();
}
static struct file_operations sf_dir_fops = {
.open = sf_dir_open,
.readdir = sf_dir_read,
};
/* iops */
/* This is called when vfs failed to locate dentry in the cache. The
job of this function is to allocate inode and link it to dentry.
[dentry] contains the name to be looked in the [parent] directory.
Failure to locate the name is not a "hard" error, in this case NULL
inode is added to [dentry] and vfs should proceed trying to create
the entry via other means. NULL(or "positive" pointer) ought to be
returned in case of succes and "negative" pointer on error */
static struct dentry *
#endif
)
{
int err;
struct sf_glob_info *sf_g;
TRACE ();
if (err) {
goto fail0;
}
if (err) {
/* -ENOENT add NULL inode to dentry so it later can be
}
else goto fail1;
}
else {
if (!sf_new_i) {
elog2 ("could not allocate memory for new inode info\n");
goto fail1;
}
if (!inode) {
elog2 ("iget failed\n");
goto fail2;
}
}
sf_i->force_restat = 0;
return NULL;
}
/* This should allocate memory for sf_inode_info, compute unique inode
number, get an inode from vfs, initialize inode info, instantiate
dentry */
static int
{
int err;
struct sf_inode_info *sf_new_i;
TRACE ();
if (!sf_new_i) {
elog3 ("%s: %s: could not allocate inode info\n",
goto fail0;
}
if (!inode) {
goto fail1;
}
return 0;
return err;
}
static int
{
TRACE ();
#if 0
#endif
params.CreateFlags = 0
| (dirop ? SHFL_CF_DIRECTORY : 0)
;
;
if (err) {
goto fail0;
}
if (VBOX_FAILURE (rc)) {
goto fail0;
}
goto fail0;
}
if (err) {
elog ("(%d): could not instantiate dentry for %s err=%d\n",
goto fail1;
}
if (VBOX_FAILURE (rc)) {
}
return 0;
if (VBOX_FAILURE (rc)) {
}
return err;
}
static int
#endif
)
{
TRACE ();
}
static int
{
TRACE ();
}
static int
{
TRACE ();
if (err) {
goto fail0;
}
if (VBOX_FAILURE (rc)) {
switch (rc) {
case VERR_PATH_NOT_FOUND:
break;
case VERR_DIR_NOT_EMPTY:
break;
default:
break;
}
goto fail1;
}
return 0;
return err;
}
static int
{
TRACE ();
}
static int
{
TRACE ();
}
static int
{
TRACE ();
elog2 ("rename with different roots\n");
return -EINVAL;
}
old_dentry, &old_path);
if (err) {
elog2 ("failed to create old path\n");
return err;
}
new_dentry, &new_path);
if (err) {
elog2 ("failed to create new path\n");
goto fail0;
}
if (VBOX_FAILURE (rc)) {
switch (rc) {
case VERR_FILE_NOT_FOUND:
case VERR_PATH_NOT_FOUND:
goto fail1;
default:
goto fail1;
}
}
err = 0;
return err;
}
static struct inode_operations sf_dir_iops = {
#else
#endif
};