patch-2.2.12 linux/fs/fcntl.c
Next file: linux/fs/file.c
Previous file: linux/fs/fat/inode.c
Back to the patch index
Back to the overall index
- Lines: 153
- Date:
Wed Aug 25 17:29:49 1999
- Orig file:
v2.2.11/linux/fs/fcntl.c
- Orig date:
Fri Nov 13 10:07:26 1998
diff -u --recursive --new-file v2.2.11/linux/fs/fcntl.c linux/fs/fcntl.c
@@ -12,14 +12,15 @@
extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
-static inline int dupfd(unsigned int fd, unsigned int arg)
+static inline int dupfd(unsigned int fd, unsigned int start)
{
struct files_struct * files = current->files;
struct file * file;
+ unsigned int newfd;
int error;
error = -EINVAL;
- if (arg >= NR_OPEN)
+ if (start >= NR_OPEN)
goto out;
error = -EBADF;
@@ -27,15 +28,39 @@
if (!file)
goto out;
+repeat:
error = -EMFILE;
- arg = find_next_zero_bit(&files->open_fds, NR_OPEN, arg);
- if (arg >= current->rlim[RLIMIT_NOFILE].rlim_cur)
+ if (start < files->next_fd)
+ start = files->next_fd;
+ /* At this point, start MUST be <= max_fdset */
+#if 1
+ if (start > files->max_fdset)
+ printk (KERN_ERR "dupfd: fd %d, max %d\n",
+ start, files->max_fdset);
+#endif
+ newfd = find_next_zero_bit(files->open_fds->fds_bits,
+ files->max_fdset,
+ start);
+ if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
goto out_putf;
- FD_SET(arg, &files->open_fds);
- FD_CLR(arg, &files->close_on_exec);
- fd_install(arg, file);
- error = arg;
+
+ error = expand_files(files, newfd);
+ if (error < 0)
+ goto out_putf;
+ if (error) /* If we might have blocked, try again. */
+ goto repeat;
+
+ FD_SET(newfd, files->open_fds);
+ FD_CLR(newfd, files->close_on_exec);
+ if (start <= files->next_fd)
+ files->next_fd = newfd + 1;
+ fd_install(newfd, file);
+ error = newfd;
out:
+#ifdef FDSET_DEBUG
+ if (error < 0)
+ printk (KERN_ERR __FUNCTION__ ": return %d\n", error);
+#endif
return error;
out_putf:
@@ -48,18 +73,30 @@
int err = -EBADF;
lock_kernel();
+#ifdef FDSET_DEBUG
+ printk (KERN_ERR __FUNCTION__ " 0: oldfd = %d, newfd = %d\n",
+ oldfd, newfd);
+#endif
if (!fcheck(oldfd))
goto out;
+ if (newfd >= NR_OPEN)
+ goto out; /* following POSIX.1 6.2.1 */
+
err = newfd;
if (newfd == oldfd)
goto out;
- err = -EBADF;
- if (newfd >= NR_OPEN)
- goto out; /* following POSIX.1 6.2.1 */
+ /* We must be able to do the fd setting inside dupfd() without
+ blocking after the sys_close(). */
+ if ((err = expand_files(current->files, newfd)) < 0)
+ goto out;
+
sys_close(newfd);
err = dupfd(oldfd, newfd);
out:
+#ifdef FDSET_DEBUG
+ printk (KERN_ERR __FUNCTION__ ": return %d\n", err);
+#endif
unlock_kernel();
return err;
}
@@ -71,6 +108,10 @@
lock_kernel();
ret = dupfd(fildes, 0);
unlock_kernel();
+#ifdef FDSET_DEBUG
+ if (ret < 0)
+ printk (KERN_ERR __FUNCTION__ ": return %d\n", ret);
+#endif
return ret;
}
@@ -111,19 +152,20 @@
filp = fget(fd);
if (!filp)
goto out;
+
err = 0;
switch (cmd) {
case F_DUPFD:
err = dupfd(fd, arg);
break;
case F_GETFD:
- err = FD_ISSET(fd, ¤t->files->close_on_exec);
+ err = FD_ISSET(fd, current->files->close_on_exec);
break;
case F_SETFD:
if (arg&1)
- FD_SET(fd, ¤t->files->close_on_exec);
+ FD_SET(fd, current->files->close_on_exec);
else
- FD_CLR(fd, ¤t->files->close_on_exec);
+ FD_CLR(fd, current->files->close_on_exec);
break;
case F_GETFL:
err = filp->f_flags;
@@ -151,7 +193,6 @@
err = filp->f_owner.pid;
break;
case F_SETOWN:
- err = 0;
filp->f_owner.pid = arg;
filp->f_owner.uid = current->uid;
filp->f_owner.euid = current->euid;
@@ -171,10 +212,9 @@
break;
default:
/* sockets need a few special fcntls. */
+ err = -EINVAL;
if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
err = sock_fcntl (filp, cmd, arg);
- else
- err = -EINVAL;
break;
}
fput(filp);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)