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  *  @brief File Descriptor Routines
0007  *  @ingroup LibIOInternal
0008  */
0009 
0010 /*
0011  *  COPYRIGHT (c) 1989-1999.
0012  *  On-Line Applications Research Corporation (OAR).
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039 
0040 #include <fcntl.h>
0041 #include <stdio.h>
0042 #include <stdlib.h>
0043 #include <string.h>
0044 #include <unistd.h>
0045 
0046 #include <rtems.h>
0047 #include <rtems/libio_.h>
0048 #include <rtems/assoc.h>
0049 
0050 /* define this to alias O_NDELAY to  O_NONBLOCK, i.e.,
0051  * O_NDELAY is accepted on input but fcntl(F_GETFL) returns
0052  * O_NONBLOCK. This is because rtems has no distinction
0053  * between the two (but some systems have).
0054  * Note that accepting this alias creates a problem:
0055  * an application trying to clear the non-blocking flag
0056  * using a
0057  *
0058  *    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NDELAY);
0059  *
0060  * does (silently) ignore the operation.
0061  */
0062 #undef ACCEPT_O_NDELAY_ALIAS
0063 
0064 static const rtems_assoc_t access_modes_assoc[] = {
0065   { "READ",       LIBIO_FLAGS_READ,  O_RDONLY },
0066   { "WRITE",      LIBIO_FLAGS_WRITE, O_WRONLY },
0067   { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
0068   { 0, 0, 0 },
0069 };
0070 
0071 static const rtems_assoc_t status_flags_assoc[] = {
0072 #ifdef ACCEPT_O_NDELAY_ALIAS
0073   { "NO DELAY",  LIBIO_FLAGS_NO_DELAY,  O_NDELAY },
0074 #endif
0075   { "NONBLOCK",  LIBIO_FLAGS_NO_DELAY,  O_NONBLOCK },
0076   { "APPEND",    LIBIO_FLAGS_APPEND,    O_APPEND },
0077   { 0, 0, 0 },
0078 };
0079 
0080 unsigned int rtems_libio_fcntl_flags( int fcntl_flags )
0081 {
0082   unsigned int   flags = 0;
0083   uint32_t   access_modes;
0084 
0085   /*
0086    * Access mode is a small integer
0087    */
0088 
0089   access_modes = (unsigned int) (fcntl_flags & O_ACCMODE);
0090   fcntl_flags &= ~O_ACCMODE;
0091   flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes );
0092 
0093   /*
0094    * Everything else is single bits
0095    */
0096 
0097   flags |= (unsigned int ) rtems_assoc_local_by_remote_bitfield(
0098     status_flags_assoc,
0099     (uint32_t) fcntl_flags
0100   );
0101 
0102   return flags;
0103 }
0104 
0105 int rtems_libio_to_fcntl_flags( unsigned int flags )
0106 {
0107   int fcntl_flags = 0;
0108 
0109   if ( (flags & LIBIO_FLAGS_READ_WRITE) == LIBIO_FLAGS_READ_WRITE ) {
0110     fcntl_flags |= O_RDWR;
0111   } else if ( (flags & LIBIO_FLAGS_READ) == LIBIO_FLAGS_READ) {
0112     fcntl_flags |= O_RDONLY;
0113   } else if ( (flags & LIBIO_FLAGS_WRITE) == LIBIO_FLAGS_WRITE) {
0114     fcntl_flags |= O_WRONLY;
0115   }
0116 
0117   if ( (flags & LIBIO_FLAGS_NO_DELAY) == LIBIO_FLAGS_NO_DELAY ) {
0118     fcntl_flags |= O_NONBLOCK;
0119   }
0120 
0121   if ( (flags & LIBIO_FLAGS_APPEND) == LIBIO_FLAGS_APPEND ) {
0122     fcntl_flags |= O_APPEND;
0123   }
0124 
0125   return fcntl_flags;
0126 }
0127 
0128 rtems_libio_t *rtems_libio_allocate( void )
0129 {
0130   rtems_libio_t *iop;
0131 
0132   rtems_libio_lock();
0133 
0134   iop = rtems_libio_iop_free_head;
0135 
0136   if ( iop != NULL ) {
0137     void *next;
0138 
0139     next = iop->data1;
0140     rtems_libio_iop_free_head = next;
0141 
0142     if ( next == NULL ) {
0143       rtems_libio_iop_free_tail = &rtems_libio_iop_free_head;
0144     }
0145   }
0146 
0147   rtems_libio_unlock();
0148 
0149   return iop;
0150 }
0151 
0152 void rtems_libio_free(
0153   rtems_libio_t *iop
0154 )
0155 {
0156   size_t zero;
0157 
0158   rtems_filesystem_location_free( &iop->pathinfo );
0159 
0160   rtems_libio_lock();
0161 
0162   /*
0163    * Clear everything except the reference count part.  At this point in time
0164    * there may be still some holders of this file descriptor.
0165    */
0166   rtems_libio_iop_flags_clear( iop, LIBIO_FLAGS_REFERENCE_INC - 1U );
0167   zero = offsetof( rtems_libio_t, offset );
0168   memset( (char *) iop + zero, 0, sizeof( *iop ) - zero );
0169 
0170   /*
0171    * Append it to the free list.  This increases the likelihood that a use
0172    * after close is detected.
0173    */
0174   *rtems_libio_iop_free_tail = iop;
0175   rtems_libio_iop_free_tail = &iop->data1;
0176 
0177   rtems_libio_unlock();
0178 }
0179 
0180 int rtems_libio_count_open_iops(
0181   void
0182 )
0183 {
0184   int open = 0;
0185   int i;
0186   /*
0187    * No locking needed to count the open iops
0188    */
0189   for (i = 0; i < rtems_libio_number_iops; ++i) {
0190     const rtems_libio_t *iop = &rtems_libio_iops[ i ];
0191     if (( rtems_libio_iop_flags( iop ) & LIBIO_FLAGS_OPEN ) != 0 ) {
0192       ++open;
0193     }
0194   }
0195   return open;
0196 }