diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-17 13:25:08 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-17 13:25:08 +0000 |
commit | 59223edaa18759982db0a8aced0e77457d10c68e (patch) | |
tree | 89354903b01fa0a447bffeefe00df3044495db2e /fs/namei.c | |
parent | db7d4daea91e105e3859cf461d7e53b9b77454b2 (diff) |
Merge with Linux 2.3.6. Sorry, this isn't tested on silicon, I don't
have a MIPS box at hand.
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 74 |
1 files changed, 48 insertions, 26 deletions
diff --git a/fs/namei.c b/fs/namei.c index b91b43a1f..9769ce1bb 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -633,6 +633,24 @@ static inline int lookup_flags(unsigned int f) return retval; } +int vfs_create(struct inode *dir, struct dentry *dentry, int mode) +{ + int error; + + error = may_create(dir, dentry); + if (error) + goto exit_lock; + + error = -EACCES; /* shouldn't it be ENOSYS? */ + if (!dir->i_op || !dir->i_op->create) + goto exit_lock; + + DQUOT_INIT(dir); + error = dir->i_op->create(dir, dentry, mode); +exit_lock: + return error; +} + /* * open_namei() * @@ -695,16 +713,11 @@ struct dentry * open_namei(const char * pathname, int flag, int mode) error = 0; if (flag & O_EXCL) error = -EEXIST; - } else if ((error = may_create(dir->d_inode, dentry)) == 0) { - if (!dir->d_inode->i_op || !dir->d_inode->i_op->create) - error = -EACCES; - else { - DQUOT_INIT(dir->d_inode); - error = dir->d_inode->i_op->create(dir->d_inode, dentry, mode); - /* Don't check for write permission, don't truncate */ - acc_mode = 0; - flag &= ~O_TRUNC; - } + } else { + error = vfs_create(dir->d_inode, dentry,mode); + /* Don't check for write permission, don't truncate */ + acc_mode = 0; + flag &= ~O_TRUNC; } unlock_dir(dir); if (error) @@ -825,41 +838,50 @@ asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev) { int error; char * tmp; + struct dentry * dentry; lock_kernel(); error = -EPERM; if (S_ISDIR(mode) || (!S_ISFIFO(mode) && !capable(CAP_SYS_ADMIN))) goto out; + tmp = getname(filename); + error = PTR_ERR(tmp); + if (IS_ERR(tmp)) + goto out; + error = -EINVAL; switch (mode & S_IFMT) { case 0: - mode |= S_IFREG; - break; - case S_IFREG: case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: + 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); + } break; - default: - goto out; - } - tmp = getname(filename); - error = PTR_ERR(tmp); - if (!IS_ERR(tmp)) { - struct dentry * dentry = do_mknod(tmp,mode,dev); - putname(tmp); + 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; } + break; } + putname(tmp); + out: unlock_kernel(); return error; } -/* - * Look out: this function may change a normal dentry - * into a directory dentry (different size).. - */ static inline int do_mkdir(const char * pathname, int mode) { int error; @@ -893,7 +915,7 @@ static inline int do_mkdir(const char * pathname, int mode) goto exit_lock; DQUOT_INIT(dir->d_inode); - mode &= 0777 & ~current->fs->umask; + mode &= (S_IRWXUGO|S_ISVTX) & ~current->fs->umask; error = dir->d_inode->i_op->mkdir(dir->d_inode, dentry, mode); exit_lock: |