Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:15

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup libcsupport
0007  *
0008  * @brief POSIX 1003.1b 6.5.2 - File Control
0009  */
0010 
0011 /*
0012  *  COPYRIGHT (c) 1989-1999.
0013  *  On-Line Applications Research Corporation (OAR).
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040 
0041 #include <stdarg.h>
0042 #include <unistd.h>
0043 #include <fcntl.h>
0044 
0045 #include <rtems/libio_.h>
0046 
0047 static int duplicate_iop( rtems_libio_t *iop )
0048 {
0049   int            rv;
0050   int            oflag;
0051   rtems_libio_t *diop;
0052 
0053   oflag = rtems_libio_to_fcntl_flags( rtems_libio_iop_flags( iop ) );
0054   diop = rtems_libio_allocate();
0055 
0056   if (diop != NULL) {
0057     rtems_filesystem_instance_lock( &iop->pathinfo );
0058     rtems_filesystem_location_clone( &diop->pathinfo, &iop->pathinfo );
0059     rtems_filesystem_instance_unlock( &iop->pathinfo );
0060 
0061     rtems_libio_iop_flags_set( diop, rtems_libio_fcntl_flags( oflag ) );
0062     /*
0063      * XXX: We call the open handler here to have a proper open and close pair.
0064      *
0065      * FIXME: What to do with the path?
0066      */
0067     rv = (*diop->pathinfo.handlers->open_h)( diop, NULL, oflag, 0 );
0068     if ( rv == 0 ) {
0069       rtems_libio_iop_flags_set( diop, LIBIO_FLAGS_OPEN );
0070       rv = rtems_libio_iop_to_descriptor( diop );
0071     } else {
0072       rtems_libio_free( diop );
0073     }
0074   } else {
0075     rv = -1;
0076   }
0077 
0078   return rv;
0079 }
0080 
0081 static int duplicate2_iop( rtems_libio_t *iop, int fd2 )
0082 {
0083   rtems_libio_t *iop2;
0084   int            rv = 0;
0085 
0086   if ( (uint32_t) fd2 >= rtems_libio_number_iops ) {
0087     rtems_set_errno_and_return_minus_one( EBADF );
0088   }
0089 
0090   iop2 = rtems_libio_iop( fd2 );
0091 
0092   if (iop != iop2)
0093   {
0094     int oflag;
0095 
0096     if ((rtems_libio_iop_flags( iop2 ) & LIBIO_FLAGS_OPEN) != 0) {
0097       rv = (*iop2->pathinfo.handlers->close_h)( iop2 );
0098     }
0099 
0100     if (rv == 0) {
0101       oflag = rtems_libio_to_fcntl_flags( rtems_libio_iop_flags( iop ) );
0102       rtems_libio_iop_flags_set( iop2, rtems_libio_fcntl_flags( oflag ) );
0103 
0104       rtems_filesystem_instance_lock( &iop->pathinfo );
0105       rtems_filesystem_location_clone( &iop2->pathinfo, &iop->pathinfo );
0106       rtems_filesystem_instance_unlock( &iop->pathinfo );
0107 
0108       /*
0109        * XXX: We call the open handler here to have a proper open and close
0110        *      pair.
0111        *
0112        * FIXME: What to do with the path?
0113        */
0114       rv = (*iop2->pathinfo.handlers->open_h)( iop2, NULL, oflag, 0 );
0115       if ( rv == 0 ) {
0116         rv = fd2;
0117       }
0118     }
0119   }
0120 
0121   return rv;
0122 }
0123 
0124 static int vfcntl(
0125   int fd,
0126   int cmd,
0127   va_list ap
0128 )
0129 {
0130   rtems_libio_t *iop;
0131   int            fd2;
0132   int            flags;
0133   int            mask;
0134   int            ret = 0;
0135 
0136   LIBIO_GET_IOP( fd, iop );
0137 
0138   /*
0139    *  Now process the fcntl().
0140    */
0141 
0142   /*
0143    *  This switch should contain all the cases from POSIX.
0144    */
0145 
0146   switch ( cmd ) {
0147     case F_DUPFD:        /* dup */
0148       ret = duplicate_iop( iop );
0149       break;
0150 
0151     case F_DUP2FD:       /* dup2 */
0152       fd2 = va_arg( ap, int );
0153       ret = duplicate2_iop( iop, fd2 );
0154       break;
0155 
0156     case F_GETFD:        /* get f_flags */
0157       ret = ((rtems_libio_iop_flags(iop) & LIBIO_FLAGS_CLOSE_ON_EXEC) != 0);
0158       break;
0159 
0160     case F_SETFD:        /* set f_flags */
0161       /*
0162        *  Interpret the third argument as the "close on exec()" flag.
0163        *  If this argument is 1, then the file descriptor is to be closed
0164        *  if a new process is exec()'ed.  Since RTEMS does not support
0165        *  processes, then we can ignore this one except to make
0166        *  F_GETFD work.
0167        */
0168 
0169       if ( va_arg( ap, int ) )
0170         rtems_libio_iop_flags_set( iop, LIBIO_FLAGS_CLOSE_ON_EXEC );
0171       else
0172         rtems_libio_iop_flags_clear( iop, LIBIO_FLAGS_CLOSE_ON_EXEC );
0173       break;
0174 
0175     case F_GETFL:        /* more flags (cloexec) */
0176       ret = rtems_libio_to_fcntl_flags( rtems_libio_iop_flags( iop ) );
0177       break;
0178 
0179     case F_SETFL:
0180       flags = rtems_libio_fcntl_flags( va_arg( ap, int ) );
0181       mask = LIBIO_FLAGS_NO_DELAY | LIBIO_FLAGS_APPEND;
0182 
0183       /*
0184        *  XXX If we are turning on append, should we seek to the end?
0185        */
0186 
0187       rtems_libio_iop_flags_clear( iop, mask );
0188       rtems_libio_iop_flags_set( iop, flags & mask );
0189       break;
0190 
0191     case F_GETLK:
0192       errno = ENOTSUP;
0193       ret = -1;
0194       break;
0195 
0196     case F_SETLK:
0197       errno = ENOTSUP;
0198       ret = -1;
0199       break;
0200 
0201     case F_SETLKW:
0202       errno = ENOTSUP;
0203       ret = -1;
0204       break;
0205 
0206     case F_SETOWN:       /*  for sockets. */
0207       errno = ENOTSUP;
0208       ret = -1;
0209       break;
0210 
0211     case F_GETOWN:       /*  for sockets. */
0212       errno = ENOTSUP;
0213       ret = -1;
0214       break;
0215 
0216     default:
0217       errno = EINVAL;
0218       ret = -1;
0219       break;
0220   }
0221 
0222   /*
0223    *  If we got this far successfully, then we give the optional
0224    *  filesystem specific handler a chance to process this.
0225    */
0226 
0227   if (ret >= 0) {
0228     int err = (*iop->pathinfo.handlers->fcntl_h)( iop, cmd );
0229     if (err) {
0230       errno = err;
0231       ret = -1;
0232     }
0233   }
0234 
0235   rtems_libio_iop_drop( iop );
0236   return ret;
0237 }
0238 
0239 int fcntl(
0240   int fd,
0241   int cmd,
0242   ...
0243 )
0244 {
0245   int            ret;
0246   va_list        ap;
0247   va_start( ap, cmd );
0248   ret = vfcntl(fd,cmd,ap);
0249   va_end(ap);
0250   return ret;
0251 }
0252 
0253 
0254 /*
0255  *  _fcntl_r
0256  *
0257  *  This is the Newlib dependent reentrant version of fcntl().
0258  */
0259 
0260 #if defined(RTEMS_NEWLIB) && !defined(HAVE_FCNTL_R)
0261 
0262 #include <reent.h>
0263 
0264 int _fcntl_r(
0265   struct _reent *ptr RTEMS_UNUSED,
0266   int fd,
0267   int cmd,
0268   int arg
0269 )
0270 {
0271   return fcntl( fd, cmd, arg );
0272 }
0273 #endif