diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-08-28 22:00:09 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-08-28 22:00:09 +0000 |
commit | 1a1d77dd589de5a567fa95e36aa6999c704ceca4 (patch) | |
tree | 141e31f89f18b9fe0831f31852e0435ceaccafc5 /fs/fcntl.c | |
parent | fb9c690a18b3d66925a65b17441c37fa14d4370b (diff) |
Merge with 2.4.0-test7.
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r-- | fs/fcntl.c | 100 |
1 files changed, 75 insertions, 25 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c index 35a5dbc7d..7a3bcefb8 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -129,7 +129,7 @@ out_putf: asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) { int err = -EBADF; - struct file * file; + struct file * file, *tofree; struct files_struct * files = current->files; write_lock(&files->file_lock); @@ -144,31 +144,40 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) get_file(file); /* We are now finished with oldfd */ err = expand_files(files, newfd); - if (err < 0) { - write_unlock(&files->file_lock); - fput(file); - goto out; - } + if (err < 0) + goto out_fput; /* To avoid races with open() and dup(), we will mark the fd as * in-use in the open-file bitmap throughout the entire dup2() * process. This is quite safe: do_close() uses the fd array * entry, not the bitmap, to decide what work needs to be * done. --sct */ + /* Doesn't work. open() might be there first. --AV */ + + /* Yes. It's a race. In user space. Nothing sane to do */ + err = -EBUSY; + tofree = files->fd[newfd]; + if (!tofree && FD_ISSET(newfd, files->open_fds)) + goto out_fput; + + files->fd[newfd] = file; FD_SET(newfd, files->open_fds); + FD_CLR(newfd, files->close_on_exec); write_unlock(&files->file_lock); - - do_close(files, newfd, 0); - write_lock(&files->file_lock); - allocate_fd(files, file, newfd); + if (tofree) + filp_close(tofree, files); err = newfd; - out: return err; out_unlock: write_unlock(&files->file_lock); goto out; + +out_fput: + write_unlock(&files->file_lock); + fput(file); + goto out; } asmlinkage long sys_dup(unsigned int fildes) @@ -209,16 +218,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg) return 0; } -asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct file * filp; - long err = -EBADF; +static long do_fcntl(unsigned int fd, unsigned int cmd, + unsigned long arg, struct file * filp) +{ + long err = 0; - filp = fget(fd); - if (!filp) - goto out; - err = 0; - lock_kernel(); switch (cmd) { case F_DUPFD: err = -EINVAL; @@ -228,13 +232,10 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) } break; case F_GETFD: - err = FD_ISSET(fd, current->files->close_on_exec); + err = get_close_on_exec(fd); break; case F_SETFD: - if (arg&1) - FD_SET(fd, current->files->close_on_exec); - else - FD_CLR(fd, current->files->close_on_exec); + set_close_on_exec(fd, arg&1); break; case F_GETFL: err = filp->f_flags; @@ -287,11 +288,60 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) err = sock_fcntl (filp, cmd, arg); break; } + + return err; +} + +asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct file * filp; + long err = -EBADF; + + filp = fget(fd); + if (!filp) + goto out; + + lock_kernel(); + err = do_fcntl(fd, cmd, arg, filp); + unlock_kernel(); + + fput(filp); +out: + return err; +} + +#if BITS_PER_LONG == 32 +asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct file * filp; + long err; + + err = -EBADF; + filp = fget(fd); + if (!filp) + goto out; + + lock_kernel(); + switch (cmd) { + case F_GETLK64: + err = fcntl_getlk64(fd, (struct flock64 *) arg); + break; + case F_SETLK64: + err = fcntl_setlk64(fd, cmd, (struct flock64 *) arg); + break; + case F_SETLKW64: + err = fcntl_setlk64(fd, cmd, (struct flock64 *) arg); + break; + default: + err = do_fcntl(fd, cmd, arg, filp); + break; + } unlock_kernel(); fput(filp); out: return err; } +#endif /* Table to convert sigio signal codes into poll band bitmaps */ |