| Kernel v2.5.75 /fs/namei.c |
|---|
 2.5.75
 fs
 namei.c
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c Thu Jul 10 13:16:27 2003
+++ b/fs/namei.c Thu Jul 10 13:16:27 2003
@@ -203,7 +203,7 @@
return -EACCES;
}
-int permission(struct inode * inode,int mask)
+int permission(struct inode * inode,int mask, struct nameidata *nd)
{
int retval;
int submask;
@@ -212,7 +212,7 @@
submask = mask & ~MAY_APPEND;
if (inode->i_op && inode->i_op->permission)
- retval = inode->i_op->permission(inode, submask);
+ retval = inode->i_op->permission(inode, submask, nd);
else
retval = vfs_permission(inode, submask);
if (retval)
@@ -273,7 +273,7 @@
* Internal lookup() using the new generic dcache.
* SMP-safe
*/
-static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
+static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
{
struct dentry * dentry = __d_lookup(parent, name);
@@ -284,7 +284,7 @@
dentry = d_lookup(parent, name);
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
+ if (!dentry->d_op->d_revalidate(dentry, nd) && !d_invalidate(dentry)) {
dput(dentry);
dentry = NULL;
}
@@ -336,7 +336,7 @@
* make sure that nobody added the entry to the dcache in the meantime..
* SMP-safe
*/
-static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
+static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
{
struct dentry * result;
struct inode *dir = parent->d_inode;
@@ -361,7 +361,7 @@
struct dentry * dentry = d_alloc(parent, name);
result = ERR_PTR(-ENOMEM);
if (dentry) {
- result = dir->i_op->lookup(dir, dentry);
+ result = dir->i_op->lookup(dir, dentry, nd);
if (result)
dput(dentry);
else
@@ -377,7 +377,7 @@
*/
up(&dir->i_sem);
if (result->d_op && result->d_op->d_revalidate) {
- if (!result->d_op->d_revalidate(result, flags) && !d_invalidate(result)) {
+ if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
dput(result);
result = ERR_PTR(-ENOENT);
}
@@ -524,7 +524,7 @@
* It _is_ time-critical.
*/
static int do_lookup(struct nameidata *nd, struct qstr *name,
- struct path *path, int flags)
+ struct path *path)
{
struct vfsmount *mnt = nd->mnt;
struct dentry *dentry = __d_lookup(nd->dentry, name);
@@ -539,13 +539,13 @@
return 0;
need_lookup:
- dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE);
+ dentry = real_lookup(nd->dentry, name, nd);
if (IS_ERR(dentry))
goto fail;
goto done;
need_revalidate:
- if (dentry->d_op->d_revalidate(dentry, flags))
+ if (dentry->d_op->d_revalidate(dentry, nd))
goto done;
if (d_invalidate(dentry))
goto done;
@@ -588,7 +588,7 @@
err = exec_permission_lite(inode);
if (err == -EAGAIN) {
- err = permission(inode, MAY_EXEC);
+ err = permission(inode, MAY_EXEC, nd);
}
if (err)
break;
@@ -638,8 +638,9 @@
if (err < 0)
break;
}
+ nd->flags |= LOOKUP_CONTINUE;
/* This does the actual lookups.. */
- err = do_lookup(nd, &this, &next, LOOKUP_CONTINUE);
+ err = do_lookup(nd, &this, &next);
if (err)
break;
/* Check mountpoints.. */
@@ -681,6 +682,7 @@
last_with_slashes:
lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
last_component:
+ nd->flags &= ~LOOKUP_CONTINUE;
if (lookup_flags & LOOKUP_PARENT)
goto lookup_parent;
if (this.name[0] == '.') switch (this.len) {
@@ -700,7 +702,7 @@
if (err < 0)
break;
}
- err = do_lookup(nd, &this, &next, 0);
+ err = do_lookup(nd, &this, &next);
if (err)
break;
follow_mount(&next.mnt, &next.dentry);
@@ -769,6 +771,7 @@
*/
nd_root.last_type = LAST_ROOT;
nd_root.flags = nd->flags;
+ memcpy(&nd_root.intent, &nd->intent, sizeof(nd_root.intent));
read_lock(¤t->fs->lock);
nd_root.mnt = mntget(current->fs->rootmnt);
nd_root.dentry = dget(current->fs->root);
@@ -866,14 +869,14 @@
* needs parent already locked. Doesn't follow mounts.
* SMP-safe.
*/
-struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
+static struct dentry * __lookup_hash(struct qstr *name, struct dentry * base, struct nameidata *nd)
{
struct dentry * dentry;
struct inode *inode;
int err;
inode = base->d_inode;
- err = permission(inode, MAY_EXEC);
+ err = permission(inode, MAY_EXEC, nd);
dentry = ERR_PTR(err);
if (err)
goto out;
@@ -889,13 +892,13 @@
goto out;
}
- dentry = cached_lookup(base, name, 0);
+ dentry = cached_lookup(base, name, nd);
if (!dentry) {
struct dentry *new = d_alloc(base, name);
dentry = ERR_PTR(-ENOMEM);
if (!new)
goto out;
- dentry = inode->i_op->lookup(inode, new);
+ dentry = inode->i_op->lookup(inode, new, nd);
if (!dentry)
dentry = new;
else
@@ -905,6 +908,11 @@
return dentry;
}
+struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
+{
+ return __lookup_hash(name, base, NULL);
+}
+
/* SMP-safe */
struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
{
@@ -988,12 +996,12 @@
* 10. We don't allow removal of NFS sillyrenamed files; it's handled by
* nfs_async_unlink().
*/
-static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
+static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir)
{
int error;
if (!victim->d_inode || victim->d_parent->d_inode != dir)
return -ENOENT;
- error = permission(dir,MAY_WRITE | MAY_EXEC);
+ error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
if (error)
return error;
if (IS_APPEND(dir))
@@ -1023,12 +1031,14 @@
* 3. We should have write and exec permissions on dir
* 4. We can't do it if dir is immutable (done in permission())
*/
-static inline int may_create(struct inode *dir, struct dentry *child) {
+static inline int may_create(struct inode *dir, struct dentry *child,
+ struct nameidata *nd)
+{
if (child->d_inode)
return -EEXIST;
if (IS_DEADDIR(dir))
return -ENOENT;
- return permission(dir,MAY_WRITE | MAY_EXEC);
+ return permission(dir,MAY_WRITE | MAY_EXEC, nd);
}
/*
@@ -1097,9 +1107,10 @@
}
}
-int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
+int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
- int error = may_create(dir, dentry);
+ int error = may_create(dir, dentry, nd);
if (error)
return error;
@@ -1112,7 +1123,7 @@
if (error)
return error;
DQUOT_INIT(dir);
- error = dir->i_op->create(dir, dentry, mode);
+ error = dir->i_op->create(dir, dentry, mode, nd);
if (!error) {
inode_dir_notify(dir, DN_CREATE);
security_inode_post_create(dir, dentry, mode);
@@ -1135,7 +1146,7 @@
if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
return -EISDIR;
- error = permission(inode, acc_mode);
+ error = permission(inode, acc_mode, nd);
if (error)
return error;
@@ -1222,11 +1233,15 @@
if (flag & O_APPEND)
acc_mode |= MAY_APPEND;
+ /* Fill in the open() intent data */
+ nd->intent.open.flags = flag;
+ nd->intent.open.create_mode = mode;
+
/*
* The simplest case - just a plain lookup.
*/
if (!(flag & O_CREAT)) {
- error = path_lookup(pathname, lookup_flags(flag), nd);
+ error = path_lookup(pathname, lookup_flags(flag)|LOOKUP_OPEN, nd);
if (error)
return error;
dentry = nd->dentry;
@@ -1236,7 +1251,7 @@
/*
* Create - we need to know the parent.
*/
- error = path_lookup(pathname, LOOKUP_PARENT, nd);
+ error = path_lookup(pathname, LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE, nd);
if (error)
return error;
@@ -1250,8 +1265,9 @@
goto exit;
dir = nd->dentry;
+ nd->flags &= ~LOOKUP_PARENT;
down(&dir->d_inode->i_sem);
- dentry = lookup_hash(&nd->last, nd->dentry);
+ dentry = __lookup_hash(&nd->last, nd->dentry, nd);
do_last:
error = PTR_ERR(dentry);
@@ -1264,7 +1280,7 @@
if (!dentry->d_inode) {
if (!IS_POSIXACL(dir->d_inode))
mode &= ~current->fs->umask;
- error = vfs_create(dir->d_inode, dentry, mode);
+ error = vfs_create(dir->d_inode, dentry, mode, nd);
up(&dir->d_inode->i_sem);
dput(nd->dentry);
nd->dentry = dentry;
@@ -1328,6 +1344,7 @@
* stored in nd->last.name and we will have to putname() it when we
* are done. Procfs-like symlinks just set LAST_BIND.
*/
+ nd->flags |= LOOKUP_PARENT;
error = security_inode_follow_link(dentry, nd);
if (error)
goto exit_dput;
@@ -1336,6 +1353,7 @@
dput(dentry);
if (error)
return error;
+ nd->flags &= ~LOOKUP_PARENT;
if (nd->last_type == LAST_BIND) {
dentry = nd->dentry;
goto ok;
@@ -1354,7 +1372,7 @@
}
dir = nd->dentry;
down(&dir->d_inode->i_sem);
- dentry = lookup_hash(&nd->last, nd->dentry);
+ dentry = __lookup_hash(&nd->last, nd->dentry, nd);
putname(nd->last.name);
goto do_last;
}
@@ -1368,6 +1386,7 @@
dentry = ERR_PTR(-EEXIST);
if (nd->last_type != LAST_NORM)
goto fail;
+ nd->flags &= ~LOOKUP_PARENT;
dentry = lookup_hash(&nd->last, nd->dentry);
if (IS_ERR(dentry))
goto fail;
@@ -1383,7 +1402,7 @@
int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
- int error = may_create(dir, dentry);
+ int error = may_create(dir, dentry, NULL);
if (error)
return error;
@@ -1431,7 +1450,7 @@
if (!IS_ERR(dentry)) {
switch (mode & S_IFMT) {
case 0: case S_IFREG:
- error = vfs_create(nd.dentry->d_inode,dentry,mode);
+ error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd);
break;
case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
error = vfs_mknod(nd.dentry->d_inode,dentry,mode,dev);
@@ -1454,7 +1473,7 @@
int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
- int error = may_create(dir, dentry);
+ int error = may_create(dir, dentry, NULL);
if (error)
return error;
@@ -1700,7 +1719,7 @@
int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
{
- int error = may_create(dir, dentry);
+ int error = may_create(dir, dentry, NULL);
if (error)
return error;
@@ -1762,7 +1781,7 @@
if (!inode)
return -ENOENT;
- error = may_create(dir, new_dentry);
+ error = may_create(dir, new_dentry, NULL);
if (error)
return error;
@@ -1883,7 +1902,7 @@
* we'll need to flip '..'.
*/
if (new_dir != old_dir) {
- error = permission(old_dentry->d_inode, MAY_WRITE);
+ error = permission(old_dentry->d_inode, MAY_WRITE, NULL);
if (error)
return error;
}
@@ -1961,7 +1980,7 @@
return error;
if (!new_dentry->d_inode)
- error = may_create(new_dir, new_dentry);
+ error = may_create(new_dir, new_dentry, NULL);
else
error = may_delete(new_dir, new_dentry, is_dir);
if (error)
|