-/*
- * locate_fd finds a free file descriptor in the open_fds fdset,
- * expanding the fd arrays if necessary. Must be called with the
- * file_lock held for write.
- */
-
-static int locate_fd(struct files_struct *files,
- struct file *file, unsigned int orig_start)
-{
- unsigned int newfd;
- unsigned int start;
- int error;
- struct fdtable *fdt;
-
- error = -EINVAL;
- if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
- goto out;
-
-repeat:
- fdt = files_fdtable(files);
- /*
- * Someone might have closed fd's in the range
- * orig_start..fdt->next_fd
- */
- start = orig_start;
- if (start < files->next_fd)
- start = files->next_fd;
-
- newfd = start;
- if (start < fdt->max_fds)
- newfd = find_next_zero_bit(fdt->open_fds->fds_bits,
- fdt->max_fds, start);
-
- error = -EMFILE;
- if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
- goto out;
-
- error = expand_files(files, newfd);
- if (error < 0)
- goto out;
-
- /*
- * If we needed to expand the fs array we
- * might have blocked - try again.
- */
- if (error)
- goto repeat;
-
- /*
- * We reacquired files_lock, so we are safe as long as
- * we reacquire the fdtable pointer and use it while holding
- * the lock, no one can free it during that time.
- */
- if (start <= files->next_fd)
- files->next_fd = newfd + 1;
-
- error = newfd;
-
-out:
- return error;
-}
-
-static int dupfd(struct file *file, unsigned int start, int cloexec)
-{
- struct files_struct * files = current->files;
- struct fdtable *fdt;
- int fd;
-
- spin_lock(&files->file_lock);
- fd = locate_fd(files, file, start);
- if (fd >= 0) {
- /* locate_fd() may have expanded fdtable, load the ptr */
- fdt = files_fdtable(files);
- FD_SET(fd, fdt->open_fds);
- if (cloexec)
- FD_SET(fd, fdt->close_on_exec);
- else
- FD_CLR(fd, fdt->close_on_exec);
- spin_unlock(&files->file_lock);
- fd_install(fd, file);
- } else {
- spin_unlock(&files->file_lock);
- fput(file);
- }
-
- return fd;
-}
-
-asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)