patch-2.4.0-test7 linux/fs/fcntl.c
Next file: linux/fs/hfs/dir_cap.c
Previous file: linux/fs/fat/dir.c
Back to the patch index
Back to the overall index
- Lines: 158
- Date:
Sat Aug 12 19:48:04 2000
- Orig file:
v2.4.0-test6/linux/fs/fcntl.c
- Orig date:
Wed Aug 9 19:19:51 2000
diff -u --recursive --new-file v2.4.0-test6/linux/fs/fcntl.c linux/fs/fcntl.c
@@ -129,7 +129,7 @@
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 @@
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 @@
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 @@
}
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 @@
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 */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)