2010-01-26 00:18:02 +01:00
|
|
|
/* This file contains routines that verify inodes and paths against the host.
|
|
|
|
*
|
|
|
|
* The entry points into this file are:
|
|
|
|
* verify_path check whether a path,inode pair is still valid
|
|
|
|
* verify_inode construct a path for an inode and verify the inode
|
|
|
|
* verify_dentry check a directory inode and look for a directory entry
|
|
|
|
*
|
|
|
|
* Created:
|
|
|
|
* April 2009 (D.C. van Moolenbroek)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "inc.h"
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* verify_path *
|
|
|
|
*===========================================================================*/
|
|
|
|
PUBLIC int verify_path(path, ino, attr, stale)
|
|
|
|
char path[PATH_MAX];
|
|
|
|
struct inode *ino;
|
|
|
|
struct hgfs_attr *attr;
|
|
|
|
int *stale;
|
|
|
|
{
|
|
|
|
/* Given a path, and the inode associated with that path, verify if the inode
|
|
|
|
* still matches the real world. Obtain the attributes of the file identified
|
|
|
|
* by the given path, and see if they match. If not, possibly mark the inode
|
|
|
|
* as deleted and return an error. Only upon success is the inode guaranteed
|
|
|
|
* to be usable.
|
|
|
|
*
|
|
|
|
* The caller must set the a_mask field of the passed attr struct.
|
|
|
|
* If 'stale' is not NULL, the value it points to must be initialized to 0,
|
|
|
|
* and will be set to 1 if the path was valid but the inode wasn't.
|
|
|
|
*/
|
|
|
|
int r;
|
|
|
|
|
|
|
|
attr->a_mask |= HGFS_ATTR_MODE;
|
|
|
|
|
|
|
|
r = hgfs_getattr(path, attr);
|
|
|
|
|
|
|
|
dprintf(("HGFS: verify_path: getattr('%s') returned %d\n", path, r));
|
|
|
|
|
|
|
|
if (r != OK) {
|
|
|
|
/* If we are told that the path does not exist, delete the inode */
|
|
|
|
if (r == ENOENT || r == ENOTDIR)
|
|
|
|
del_dentry(ino);
|
|
|
|
|
|
|
|
return r; /* path isn't valid */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the file type (reg, dir) isn't what we thought, delete the inode */
|
|
|
|
if ((ino->i_flags & I_DIR) != MODE_TO_DIRFLAG(attr->a_mode)) {
|
|
|
|
del_dentry(ino);
|
|
|
|
|
|
|
|
if (stale != NULL) *stale = 1;
|
|
|
|
return ENOENT; /* path is valid, inode wasn't */
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK; /* path and inode are valid */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* verify_inode *
|
|
|
|
*===========================================================================*/
|
|
|
|
PUBLIC int verify_inode(ino, path, attr)
|
|
|
|
struct inode *ino; /* inode to verify */
|
|
|
|
char path[PATH_MAX]; /* buffer in which to store the path */
|
|
|
|
struct hgfs_attr *attr; /* buffer for attributes, or NULL */
|
|
|
|
{
|
|
|
|
/* Given an inode, construct a path identifying the inode, and check whether
|
|
|
|
* that path is still valid for that inode (as far as we can tell). As a side
|
|
|
|
* effect, store attributes in the given attribute structure if not NULL (its
|
|
|
|
* a_mask member must then be set).
|
|
|
|
*/
|
|
|
|
struct hgfs_attr attr2;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if ((r = make_path(path, ino)) != OK) return r;
|
|
|
|
|
|
|
|
if (attr == NULL) {
|
|
|
|
attr2.a_mask = 0;
|
|
|
|
|
|
|
|
attr = &attr2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return verify_path(path, ino, attr, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* verify_dentry *
|
|
|
|
*===========================================================================*/
|
|
|
|
PUBLIC int verify_dentry(parent, name, path, res_ino)
|
|
|
|
struct inode *parent; /* parent inode: the inode to verify */
|
|
|
|
char name[NAME_MAX+1]; /* the given directory entry path component */
|
|
|
|
char path[PATH_MAX]; /* buffer to store the resulting path in */
|
|
|
|
struct inode **res_ino; /* pointer for addressed inode (or NULL) */
|
|
|
|
{
|
|
|
|
/* Given a directory inode and a name, construct a path identifying that
|
|
|
|
* directory entry, check whether the path to the parent is still valid, and
|
|
|
|
* check whether there is an inode pointed to by the full path. Upon success,
|
|
|
|
* res_ino will contain either the inode for the full path, with increased
|
2010-05-10 15:26:00 +02:00
|
|
|
* refcount, or NULL if no such inode exists.
|
2010-01-26 00:18:02 +01:00
|
|
|
*/
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if ((r = verify_inode(parent, path, NULL)) != OK)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
dprintf(("HGFS: verify_dentry: given path is '%s', name '%s'\n", path,
|
|
|
|
name));
|
|
|
|
|
|
|
|
if ((r = push_path(path, name)) != OK)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
dprintf(("HGFS: verify_dentry: path now '%s'\n", path));
|
|
|
|
|
|
|
|
*res_ino = lookup_dentry(parent, name);
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|