patch-2.0.2 linux/fs/open.c
Next file: linux/fs/pipe.c
Previous file: linux/fs/fcntl.c
Back to the patch index
Back to the overall index
- Lines: 126
- Date:
Fri Jul 5 09:27:10 1996
- Orig file:
v2.0.1/linux/fs/open.c
- Orig date:
Wed Jul 3 22:05:19 1996
diff -u --recursive --new-file v2.0.1/linux/fs/open.c linux/fs/open.c
@@ -19,6 +19,7 @@
#include <linux/mm.h>
#include <asm/segment.h>
+#include <asm/bitops.h>
asmlinkage int sys_statfs(const char * path, struct statfs * buf)
{
@@ -496,11 +497,11 @@
* for the internal routines (ie open_namei()/follow_link() etc). 00 is
* used by symlinks.
*/
-int do_open(const char * filename,int flags,int mode)
+static int do_open(const char * filename,int flags,int mode, int fd)
{
struct inode * inode;
struct file * f;
- int flag,error,fd;
+ int flag,error;
f = get_empty_filp();
if (!f)
@@ -533,21 +534,9 @@
}
f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
- /*
- * We have to do this last, because we mustn't export
- * an incomplete fd to other processes which may share
- * the same file table with us.
- */
- for(fd = 0; fd < NR_OPEN && fd < current->rlim[RLIMIT_NOFILE].rlim_cur; fd++) {
- if (!current->files->fd[fd]) {
- current->files->fd[fd] = f;
- FD_CLR(fd,¤t->files->close_on_exec);
- return fd;
- }
- }
- error = -EMFILE;
- if (f->f_op && f->f_op->release)
- f->f_op->release(inode,f);
+ current->files->fd[fd] = f;
+ return 0;
+
cleanup_all:
if (f->f_mode & FMODE_WRITE)
put_write_access(inode);
@@ -558,16 +547,44 @@
return error;
}
+/*
+ * Find a empty file descriptor entry, and mark it busy
+ */
+int get_unused_fd(void)
+{
+ int fd;
+ struct files_struct * files = current->files;
+
+ fd = find_first_zero_bit(&files->open_fds, NR_OPEN);
+ if (fd < current->rlim[RLIMIT_NOFILE].rlim_cur) {
+ FD_SET(fd, &files->open_fds);
+ FD_CLR(fd, &files->close_on_exec);
+ return fd;
+ }
+ return -EMFILE;
+}
+
+inline void put_unused_fd(int fd)
+{
+ FD_CLR(fd, ¤t->files->open_fds);
+}
+
asmlinkage int sys_open(const char * filename,int flags,int mode)
{
char * tmp;
- int error;
+ int fd, error;
+ fd = get_unused_fd();
+ if (fd < 0)
+ return fd;
error = getname(filename, &tmp);
- if (error)
- return error;
- error = do_open(tmp,flags,mode);
- putname(tmp);
+ if (!error) {
+ error = do_open(tmp,flags,mode, fd);
+ putname(tmp);
+ if (!error)
+ return fd;
+ }
+ put_unused_fd(fd);
return error;
}
@@ -610,16 +627,20 @@
}
asmlinkage int sys_close(unsigned int fd)
-{
+{
+ int error;
struct file * filp;
+ struct files_struct * files;
- if (fd >= NR_OPEN)
- return -EBADF;
- FD_CLR(fd, ¤t->files->close_on_exec);
- if (!(filp = current->files->fd[fd]))
- return -EBADF;
- current->files->fd[fd] = NULL;
- return (close_fp (filp));
+ files = current->files;
+ error = -EBADF;
+ if (fd < NR_OPEN && (filp = files->fd[fd]) != NULL) {
+ put_unused_fd(fd);
+ FD_CLR(fd, &files->close_on_exec);
+ files->fd[fd] = NULL;
+ error = close_fp(filp);
+ }
+ return error;
}
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov