From 6122cb6af67c88550fecaa786c1dfd3bc1ceb1d1 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Tue, 10 Dec 2013 12:35:29 +1100 Subject: PR2158: Add support for dup2. Split the dub call into dup and dup2 in fcntl.c. This requires a private command which is placed in the internal libio header. --- cpukit/libcsupport/src/fcntl.c | 53 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 6 deletions(-) (limited to 'cpukit/libcsupport/src/fcntl.c') diff --git a/cpukit/libcsupport/src/fcntl.c b/cpukit/libcsupport/src/fcntl.c index 53feb669b1..d422a48936 100644 --- a/cpukit/libcsupport/src/fcntl.c +++ b/cpukit/libcsupport/src/fcntl.c @@ -24,14 +24,10 @@ #include -static int duplicate_iop( rtems_libio_t *iop, int fd2 ) +static int duplicate_iop( rtems_libio_t *iop ) { int rv = 0; - /* - * FIXME: We ignore the start value fd2 for the file descriptor search. This - * is not POSIX conform. - */ rtems_libio_t *diop = rtems_libio_allocate(); if (diop != NULL) { @@ -62,6 +58,47 @@ static int duplicate_iop( rtems_libio_t *iop, int fd2 ) return rv; } +static int duplicate2_iop( rtems_libio_t *iop, int fd2 ) +{ + rtems_libio_t *iop2; + int rv = 0; + + rtems_libio_check_fd( fd2 ); + iop2 = rtems_libio_iop( fd2 ); + + if (iop != iop2) + { + int oflag; + + if ((iop2->flags & LIBIO_FLAGS_OPEN) != 0) { + rv = (*iop2->pathinfo.handlers->close_h)( iop2 ); + } + + if (rv == 0) { + oflag = rtems_libio_to_fcntl_flags( iop->flags ); + oflag &= ~O_CREAT; + iop2->flags |= rtems_libio_fcntl_flags( oflag ); + + rtems_filesystem_instance_lock( &iop->pathinfo ); + rtems_filesystem_location_clone( &iop2->pathinfo, &iop->pathinfo ); + rtems_filesystem_instance_unlock( &iop->pathinfo ); + + /* + * XXX: We call the open handler here to have a proper open and close + * pair. + * + * FIXME: What to do with the path? + */ + rv = (*iop2->pathinfo.handlers->open_h)( iop2, NULL, oflag, 0 ); + if ( rv == 0 ) { + rv = fd2; + } + } + } + + return rv; +} + static int vfcntl( int fd, int cmd, @@ -88,8 +125,12 @@ static int vfcntl( switch ( cmd ) { case F_DUPFD: /* dup */ + ret = duplicate_iop( iop ); + break; + + case F_DUP2FD: /* dup2 */ fd2 = va_arg( ap, int ); - ret = duplicate_iop( iop, fd2 ); + ret = duplicate2_iop( iop, fd2 ); break; case F_GETFD: /* get f_flags */ -- cgit v1.2.3