aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fcntl.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2007-10-17 02:30:26 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:43:01 -0400
commit22d2b35b200f76085c16a2e14ca30b58510fcbe7 (patch)
tree669ce98845b73c0a2e12b37beaa24aed8481e1d2 /fs/fcntl.c
parent18796aa00243a594a2bd6733f1360aa38c3cd8f4 (diff)
F_DUPFD_CLOEXEC implementation
One more small change to extend the availability of creation of file descriptors with FD_CLOEXEC set. Adding a new command to fcntl() requires no new system call and the overall impact on code size if minimal. If this patch gets accepted we will also add this change to the next revision of the POSIX spec. To test the patch, use the following little program. Adjust the value of F_DUPFD_CLOEXEC appropriately. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #ifndef F_DUPFD_CLOEXEC # define F_DUPFD_CLOEXEC 12 #endif int main (int argc, char *argv[]) { if (argc > 1) { if (fcntl (3, F_GETFD) == 0) { puts ("descriptor not closed"); exit (1); } if (errno != EBADF) { puts ("error not EBADF"); exit (1); } exit (0); } int fd = fcntl (STDOUT_FILENO, F_DUPFD_CLOEXEC, 0); if (fd == -1 && errno == EINVAL) { puts ("F_DUPFD_CLOEXEC not supported"); return 0; } if (fd != 3) { puts ("program called with descriptors other than 0,1,2"); return 1; } execl ("/proc/self/exe", "/proc/self/exe", "1", NULL); puts ("execl failed"); return 1; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Ulrich Drepper <drepper@redhat.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de> Cc: <linux-arch@vger.kernel.org> Cc: Kyle McMartin <kyle@mcmartin.ca> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r--fs/fcntl.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 78b2ff044054..c9db73fc5e3d 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -110,7 +110,7 @@ out:
110 return error; 110 return error;
111} 111}
112 112
113static int dupfd(struct file *file, unsigned int start) 113static int dupfd(struct file *file, unsigned int start, int cloexec)
114{ 114{
115 struct files_struct * files = current->files; 115 struct files_struct * files = current->files;
116 struct fdtable *fdt; 116 struct fdtable *fdt;
@@ -122,7 +122,10 @@ static int dupfd(struct file *file, unsigned int start)
122 /* locate_fd() may have expanded fdtable, load the ptr */ 122 /* locate_fd() may have expanded fdtable, load the ptr */
123 fdt = files_fdtable(files); 123 fdt = files_fdtable(files);
124 FD_SET(fd, fdt->open_fds); 124 FD_SET(fd, fdt->open_fds);
125 FD_CLR(fd, fdt->close_on_exec); 125 if (cloexec)
126 FD_SET(fd, fdt->close_on_exec);
127 else
128 FD_CLR(fd, fdt->close_on_exec);
126 spin_unlock(&files->file_lock); 129 spin_unlock(&files->file_lock);
127 fd_install(fd, file); 130 fd_install(fd, file);
128 } else { 131 } else {
@@ -195,7 +198,7 @@ asmlinkage long sys_dup(unsigned int fildes)
195 struct file * file = fget(fildes); 198 struct file * file = fget(fildes);
196 199
197 if (file) 200 if (file)
198 ret = dupfd(file, 0); 201 ret = dupfd(file, 0, 0);
199 return ret; 202 return ret;
200} 203}
201 204
@@ -319,8 +322,9 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
319 322
320 switch (cmd) { 323 switch (cmd) {
321 case F_DUPFD: 324 case F_DUPFD:
325 case F_DUPFD_CLOEXEC:
322 get_file(filp); 326 get_file(filp);
323 err = dupfd(filp, arg); 327 err = dupfd(filp, arg, cmd == F_DUPFD_CLOEXEC);
324 break; 328 break;
325 case F_GETFD: 329 case F_GETFD:
326 err = get_close_on_exec(fd) ? FD_CLOEXEC : 0; 330 err = get_close_on_exec(fd) ? FD_CLOEXEC : 0;