Index: dir.c =================================================================== RCS file: /cvsroot/nfs/kernel/linux-2.2/fs/nfs/dir.c,v retrieving revision 1.16 diff -u -w -r1.16 dir.c --- dir.c 1999/12/20 12:42:01 1.16 +++ dir.c 2000/01/05 22:51:36 @@ -58,6 +58,7 @@ static int nfs_mknod(struct inode *, struct dentry *, int, int); static int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); +int nfs_permission(struct inode *i, int msk); static struct file_operations nfs_dir_operations = { NULL, /* lseek - default */ @@ -90,7 +91,7 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL, /* permission */ + nfs_permission, /* permission */ NULL, /* smap */ NULL, /* updatepage */ nfs_revalidate, /* revalidate */ @@ -687,7 +688,7 @@ static struct dentry *nfs_lookup(struct inode *dir_i, struct dentry * dentry) { - struct dentry *dir = dentry->d_parent; + struct dentry *dir = dentry->d_parent, *tmp; struct inode *inode; int error; struct nfs_fh fhandle; @@ -716,9 +717,9 @@ if (inode) goto no_entry; #endif - error = NFS_CALL(lookup, dir_i, (dir, &dir_attr, - &dentry->d_name, &fhandle, &fattr)); + &dentry->d_name, + &fhandle, &fattr)); nfs_refresh_inode(dir_i, &dir_attr); inode = NULL; if (error == -ENOENT) @@ -1347,6 +1348,30 @@ if (dentry) dput(dentry); return error; +} + +int +nfs_permission(struct inode *i, int msk) +{ + struct nfs_fattr fattr; + struct dentry *de = NULL; + int err; + struct list_head *start, *tmp; + + if (!i || !i->i_sb || !NFS_SERVER(i) || !NFS_CLIENT(i) || + !NFS_PROTO(i) || !NFS_PROTO(i)->access) + return 0; + tmp = start = &i->i_dentry; + while ((tmp = tmp->next) != start) { + de = list_entry(tmp, struct dentry, d_alias); + if (de->d_inode == i) + break; + } + if (!de || de->d_inode != i || !NFS_DENTRY(de)) + return 0; + err = NFS_CALL(access, i, (de, msk, &fattr)); + nfs_refresh_inode(i, &fattr); + return err; } /* Index: file.c =================================================================== RCS file: /cvsroot/nfs/kernel/linux-2.2/fs/nfs/file.c,v retrieving revision 1.5 diff -u -w -r1.5 file.c --- file.c 1999/12/09 14:46:20 1.5 +++ file.c 2000/01/05 21:58:01 @@ -44,6 +44,7 @@ static ssize_t nfs_file_write(struct file *, const char *, size_t, loff_t *); static int nfs_file_flush(struct file *); static int nfs_fsync(struct file *, struct dentry *dentry); +int nfs_permission(struct inode *, int); static struct file_operations nfs_file_operations = { NULL, /* lseek - default */ @@ -80,7 +81,7 @@ nfs_writepage, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL, /* permission */ + nfs_permission, /* permission */ NULL, /* smap */ nfs_updatepage, /* updatepage */ nfs_revalidate, /* revalidate */ Index: nfs3proc.c =================================================================== RCS file: /cvsroot/nfs/kernel/linux-2.2/fs/nfs/nfs3proc.c,v retrieving revision 1.4 diff -u -w -r1.4 nfs3proc.c --- nfs3proc.c 1999/11/19 17:10:38 1.4 +++ nfs3proc.c 2000/01/05 21:58:01 @@ -105,6 +105,13 @@ arg.access |= NFS3_ACCESS_READ; if (mode & MAY_WRITE) arg.access |= NFS3_ACCESS_MODIFY; + if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) { + if (mode & MAY_EXEC) + arg.access |= NFS3_ACCESS_LOOKUP; + } else { + if (mode & MAY_EXEC) + arg.access |= NFS3_ACCESS_EXECUTE; + } status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_ACCESS, &arg, &res, 0); dprintk("NFS reply access\n");