patch-2.3.50 linux/fs/namei.c
Next file: linux/fs/ncpfs/dir.c
Previous file: linux/fs/msdos/namei.c
Back to the patch index
Back to the overall index
- Lines: 323
- Date:
Tue Mar 7 11:12:28 2000
- Orig file:
v2.3.49/linux/fs/namei.c
- Orig date:
Thu Feb 10 17:11:18 2000
diff -u --recursive --new-file v2.3.49/linux/fs/namei.c linux/fs/namei.c
@@ -403,10 +403,10 @@
if (IS_ERR(dentry))
break;
}
- }
- /* Check mountpoints.. */
- dentry = follow_mount(dentry);
+ /* Check mountpoints.. */
+ dentry = follow_mount(dentry);
+ }
base = do_follow_link(base, dentry, flags);
if (IS_ERR(base))
@@ -577,6 +577,9 @@
{
int error;
+ mode &= S_IALLUGO & ~current->fs->umask;
+ mode |= S_IFREG;
+
error = may_create(dir, dentry);
if (error)
goto exit_lock;
@@ -610,9 +613,6 @@
struct inode *inode;
struct dentry *dentry;
- mode &= S_IALLUGO & ~current->fs->umask;
- mode |= S_IFREG;
-
dentry = lookup_dentry(pathname, NULL, lookup_flags(flag));
if (IS_ERR(dentry))
return dentry;
@@ -739,14 +739,36 @@
return ERR_PTR(error);
}
+int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+{
+ int error = -EPERM;
+
+ mode &= ~current->fs->umask;
+
+ if (!S_ISFIFO(mode) && !capable(CAP_MKNOD))
+ goto exit_lock;
+
+ error = may_create(dir, dentry);
+ if (error)
+ goto exit_lock;
+
+ error = -EPERM;
+ if (!dir->i_op || !dir->i_op->mknod)
+ goto exit_lock;
+
+ DQUOT_INIT(dir);
+ error = dir->i_op->mknod(dir, dentry, mode, dev);
+exit_lock:
+ return error;
+}
+
struct dentry * do_mknod(const char * filename, int mode, dev_t dev)
{
int error;
struct dentry *dir;
struct dentry *dentry, *retval;
- mode &= ~current->fs->umask;
- dentry = lookup_dentry(filename, NULL, LOOKUP_FOLLOW);
+ dentry = lookup_dentry(filename, NULL, 0);
if (IS_ERR(dentry))
return dentry;
@@ -755,16 +777,8 @@
if (!check_parent(dir, dentry))
goto exit_lock;
- error = may_create(dir->d_inode, dentry);
- if (error)
- goto exit_lock;
-
- error = -EPERM;
- if (!dir->d_inode->i_op || !dir->d_inode->i_op->mknod)
- goto exit_lock;
+ error = vfs_mknod(dir->d_inode, dentry, mode, dev);
- DQUOT_INIT(dir->d_inode);
- error = dir->d_inode->i_op->mknod(dir->d_inode, dentry, mode, dev);
exit_lock:
retval = ERR_PTR(error);
if (!error)
@@ -778,47 +792,66 @@
{
int error;
char * tmp;
- struct dentry * dentry;
+ struct dentry * dentry, *dir;
- if (S_ISDIR(mode) || (!S_ISFIFO(mode) && !capable(CAP_MKNOD)))
+ if (S_ISDIR(mode))
return -EPERM;
tmp = getname(filename);
if (IS_ERR(tmp))
return PTR_ERR(tmp);
- error = -EINVAL;
lock_kernel();
+ dentry = lookup_dentry(tmp, NULL, 0);
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
+ goto out;
+ dir = lock_parent(dentry);
+ error = -ENOENT;
+ if (!check_parent(dir, dentry))
+ goto out_unlock;
switch (mode & S_IFMT) {
- case 0:
- mode |= S_IFREG; /* fallthrough */
- case S_IFREG:
- mode &= ~current->fs->umask;
- dentry = lookup_dentry(filename, NULL, LOOKUP_FOLLOW);
- if (IS_ERR(dentry))
- error = PTR_ERR(dentry);
- else {
- struct dentry *dir = lock_parent(dentry);
- error = -ENOENT;
- if (check_parent(dir, dentry))
- error = vfs_create(dir->d_inode, dentry, mode);
- dput(dentry);
- }
+ case 0: case S_IFREG:
+ error = vfs_create(dir->d_inode, dentry, mode);
break;
case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
- dentry = do_mknod(tmp,mode,dev);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- dput(dentry);
- error = 0;
- }
+ error = vfs_mknod(dir->d_inode, dentry, mode, dev);
+ break;
+ case S_IFDIR:
+ error = -EPERM;
break;
+ default:
+ error = -EINVAL;
}
+out_unlock:
+ unlock_dir(dir);
+ dput(dentry);
+out:
unlock_kernel();
putname(tmp);
return error;
}
+int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+ int error;
+
+ error = may_create(dir, dentry);
+ if (error)
+ goto exit_lock;
+
+ error = -EPERM;
+ if (!dir->i_op || !dir->i_op->mkdir)
+ goto exit_lock;
+
+ DQUOT_INIT(dir);
+ mode &= (S_IRWXUGO|S_ISVTX) & ~current->fs->umask;
+ error = dir->i_op->mkdir(dir, dentry, mode);
+
+exit_lock:
+ return error;
+}
+
static inline int do_mkdir(const char * pathname, int mode)
{
int error;
@@ -843,17 +876,7 @@
if (!check_parent(dir, dentry))
goto exit_lock;
- error = may_create(dir->d_inode, dentry);
- if (error)
- goto exit_lock;
-
- error = -EPERM;
- if (!dir->d_inode->i_op || !dir->d_inode->i_op->mkdir)
- goto exit_lock;
-
- DQUOT_INIT(dir->d_inode);
- mode &= (S_IRWXUGO|S_ISVTX) & ~current->fs->umask;
- error = dir->d_inode->i_op->mkdir(dir->d_inode, dentry, mode);
+ error = vfs_mkdir(dir->d_inode, dentry, mode);
exit_lock:
unlock_dir(dir);
@@ -1027,6 +1050,25 @@
return error;
}
+int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
+{
+ int error;
+
+ error = may_create(dir, dentry);
+ if (error)
+ goto exit_lock;
+
+ error = -EPERM;
+ if (!dir->i_op || !dir->i_op->symlink)
+ goto exit_lock;
+
+ DQUOT_INIT(dir);
+ error = dir->i_op->symlink(dir, dentry, oldname);
+
+exit_lock:
+ return error;
+}
+
static inline int do_symlink(const char * oldname, const char * newname)
{
int error;
@@ -1044,16 +1086,7 @@
if (!check_parent(dir, dentry))
goto exit_lock;
- error = may_create(dir->d_inode, dentry);
- if (error)
- goto exit_lock;
-
- error = -EPERM;
- if (!dir->d_inode->i_op || !dir->d_inode->i_op->symlink)
- goto exit_lock;
-
- DQUOT_INIT(dir->d_inode);
- error = dir->d_inode->i_op->symlink(dir->d_inode, dentry, oldname);
+ error = vfs_symlink(dir->d_inode, dentry, oldname);
exit_lock:
unlock_dir(dir);
@@ -1083,10 +1116,43 @@
return error;
}
+int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
+{
+ struct inode *inode;
+ int error;
+
+ error = -ENOENT;
+ inode = old_dentry->d_inode;
+ if (!inode)
+ goto exit_lock;
+
+ error = may_create(dir, new_dentry);
+ if (error)
+ goto exit_lock;
+
+ error = -EXDEV;
+ if (dir->i_dev != inode->i_dev)
+ goto exit_lock;
+
+ /*
+ * A link to an append-only or immutable file cannot be created.
+ */
+ error = -EPERM;
+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+ goto exit_lock;
+ if (!dir->i_op || !dir->i_op->link)
+ goto exit_lock;
+
+ DQUOT_INIT(dir);
+ error = dir->i_op->link(old_dentry, dir, new_dentry);
+
+exit_lock:
+ return error;
+}
+
static inline int do_link(const char * oldname, const char * newname)
{
struct dentry *old_dentry, *new_dentry, *dir;
- struct inode *inode;
int error;
/*
@@ -1113,32 +1179,7 @@
if (!check_parent(dir, new_dentry))
goto exit_lock;
- error = -ENOENT;
- inode = old_dentry->d_inode;
- if (!inode)
- goto exit_lock;
-
- error = may_create(dir->d_inode, new_dentry);
- if (error)
- goto exit_lock;
-
- error = -EXDEV;
- if (dir->d_inode->i_dev != inode->i_dev)
- goto exit_lock;
-
- /*
- * A link to an append-only or immutable file cannot be created.
- */
- error = -EPERM;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- goto exit_lock;
-
- error = -EPERM;
- if (!dir->d_inode->i_op || !dir->d_inode->i_op->link)
- goto exit_lock;
-
- DQUOT_INIT(dir->d_inode);
- error = dir->d_inode->i_op->link(old_dentry, dir->d_inode, new_dentry);
+ error = vfs_link(old_dentry, dir->d_inode, new_dentry);
exit_lock:
unlock_dir(dir);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)