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/include/rtems/libio_.h | 7 ++++ cpukit/libcsupport/src/dup2.c | 2 +- cpukit/libcsupport/src/fcntl.c | 53 +++++++++++++++++++++++++++---- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/cpukit/libcsupport/include/rtems/libio_.h b/cpukit/libcsupport/include/rtems/libio_.h index 885656616f..bf01cd5659 100644 --- a/cpukit/libcsupport/include/rtems/libio_.h +++ b/cpukit/libcsupport/include/rtems/libio_.h @@ -41,6 +41,13 @@ extern "C" { #define RTEMS_FILESYSTEM_SYMLOOP_MAX 32 +/* + * Not defined in newlib so provide here. Users should use dup2 and + * not this non-portable fcntl command. Provided here to allow the + * RTEMS implementation to work. + */ +#define F_DUP2FD 20 + /* * Semaphore to protect the io table */ diff --git a/cpukit/libcsupport/src/dup2.c b/cpukit/libcsupport/src/dup2.c index 37c93a7398..ac6f0a1b62 100644 --- a/cpukit/libcsupport/src/dup2.c +++ b/cpukit/libcsupport/src/dup2.c @@ -54,5 +54,5 @@ int dup2( * This fcntl handles everything else. */ - return fcntl( fildes, F_DUPFD, fildes2 ); + return fcntl( fildes, F_DUP2FD, fildes2 ); } 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