summaryrefslogblamecommitdiffstats
path: root/c/src/lib/libc/libio.c
blob: e63a4626d43f8a8a890ef1bd5120ea88705d8c61 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  













                                                                    
  


        
                                                                   

  

                                                              

   



                                                 
 
  






                                                                     

   


                                            

 

                                                                       


                                                       
 
                                                 


  


                                                                 

   
                             
 



































                                                                               


  


                                                                     


                                      



                                                   


                                      



                                                   

  


                                   
 

                          
 






                                                                          
 


                                   
 


                                                                           

 





                                                                    
 
                                           
 



















                                                                                
    



                                    
       

          
     

                                                   

 





                                                                             
 


                      
 
                                                                                
 

                                     
 
                                      
 

                                                   
 









                                                                             
 


                                                    
 

                                
 
                                                                                
 


                                                
 
                                                                      
 
                                               
 



                                                              
 



                                                     
     
   
 
                                                   
 
                

 







                                                                           
 





                               
 
                                                                                
 


                                                
 
                                                                      
 
                                               
 



                                                              
 





                                                        
 
                                                   
 
                
 
/*
 *  This file contains the support infrastructure used to manage the
 *  table of integer style file descriptors used by the low level
 *  POSIX system calls like open(), read, fstat(), etc.
 *
 *  This provides the foundation for POSIX compliant IO system calls
 *  for RTEMS.
 *
 *  COPYRIGHT (c) 1989-1998.
 *  On-Line Applications Research Corporation (OAR).
 *  Copyright assigned to U.S. Government, 1994.
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.OARcorp.com/rtems/license.html.
 *
 *  $Id$
 */

#include "libio_.h"                   /* libio_.h pulls in rtems */

/*
 *  Global variables used to manage the File Descriptor Table.
 *  IOP = IO Pointer.
 */

rtems_id                rtems_libio_semaphore;
rtems_libio_t          *rtems_libio_iops;
rtems_libio_t          *rtems_libio_last_iop;
rtems_libio_handler_t   rtems_libio_handlers[15];

/*
 *  rtems_register_libio_handler
 *
 *  This function registers an external IO handler set.  This lets
 *  other subsystems have their own versions of many of the system
 *  calls.  For example, the networking code registers handlers which
 *  map the system calls for read() and write() to socket calls.
 *
 */

void rtems_register_libio_handler(
  int                          handler_flag,
  const rtems_libio_handler_t *handler
)
{
  int handler_index = rtems_file_descriptor_type_index( handler_flag );


  if ((handler_index < 0) || (handler_index >= 15))
    rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );

  rtems_libio_handlers[handler_index] = *handler;
}

/*
 *  rtems_libio_init
 *
 *  Called by BSP startup code to initialize the libio subsystem.
 */

void rtems_libio_init( void )
{
  rtems_status_code rc;

  /*
   *  Allocate memory for the IOP Table
   */

  if ( rtems_libio_number_iops > 0 ) {
    rtems_libio_iops =
      (rtems_libio_t *) calloc(rtems_libio_number_iops, sizeof(rtems_libio_t));

    if (rtems_libio_iops == NULL)
        rtems_fatal_error_occurred( RTEMS_NO_MEMORY );

    rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1);
  }

  /*
   *  Create the binary semaphore used to provide mutual exclusion
   *  on the IOP Table.
   */

  rc = rtems_semaphore_create(
    RTEMS_LIBIO_SEM,
    1,
    RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
    RTEMS_NO_PRIORITY,
    &rtems_libio_semaphore
  );
  if ( rc != RTEMS_SUCCESSFUL )
    rtems_fatal_error_occurred( rc );

  /*
   *  Initialize the base file system infrastructure.
   */

  rtems_filesystem_initialize();
}

/*
 *  rtems_libio_fcntl_flags
 * 
 *  Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
 */

rtems_assoc_t access_modes_assoc[] = {
  { "READ",       LIBIO_FLAGS_READ,  O_RDONLY },
  { "WRITE",      LIBIO_FLAGS_WRITE, O_WRONLY },
  { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
  { 0, 0, 0 },
};

rtems_assoc_t status_flags_assoc[] = {
  { "NO DELAY",  LIBIO_FLAGS_NO_DELAY,  O_NDELAY },
  { "APPEND",    LIBIO_FLAGS_APPEND,    O_APPEND },
  { "CREATE",    LIBIO_FLAGS_CREATE,    O_CREAT },
  { 0, 0, 0 },
};

unsigned32 rtems_libio_fcntl_flags(
  unsigned32 fcntl_flags
)
{
  unsigned32 flags = 0;
  unsigned32 access_modes;

  /*
   * Access mode is a small integer
   */
  
  access_modes = fcntl_flags & O_ACCMODE;
  fcntl_flags &= ~O_ACCMODE;
  flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes );

  /*
   * Everything else is single bits
   */

  flags |=
     rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
  return flags;
}

/*
 *  rtems_libio_allocate
 *
 *  This routine searches the IOP Table for an unused entry.  If it 
 *  finds one, it returns it.  Otherwise, it returns NULL.
 */

rtems_libio_t *rtems_libio_allocate( void )
{
  rtems_libio_t *iop;
  rtems_status_code rc;
  
  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );

  for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++)
    if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) {
      /*
       *  Got an IOP -- create a semaphore for it.
       */

      rc = rtems_semaphore_create(
        RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
        1,
        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
        RTEMS_NO_PRIORITY,
        &iop->sem
      );
      if ( rc != RTEMS_SUCCESSFUL )
        goto failed;
    
      iop->flags = LIBIO_FLAGS_OPEN;
      goto done;
  }
  
failed:
  iop = 0;
  
done:
  rtems_semaphore_release( rtems_libio_semaphore );
  return iop;
}

/*
 *  rtems_libio_free
 *
 *  This routine frees the resources associated with an IOP (file descriptor)
 *  and clears the slot in the IOP Table.
 */

void rtems_libio_free(
  rtems_libio_t *iop
)
{
  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );

  if (iop->sem)
    rtems_semaphore_delete(iop->sem);

  (void) memset(iop, 0, sizeof(*iop));

  rtems_semaphore_release( rtems_libio_semaphore );
}

/*
 *  rtems_libio_is_open_files_in_fs
 *
 *  This routine scans the entire file descriptor table to determine if the
 *  are any active file descriptors that refer to the atleast one node in the
 *  file system that we are trying to dismount.
 *
 *  If there is at least one node in the file system referenced by the mount 
 *  table entry a 1 is returned, otherwise a 0 is returned.
 */

int rtems_libio_is_open_files_in_fs(
  rtems_filesystem_mount_table_entry_t * fs_mt_entry
)
{
  rtems_libio_t     *iop;
  int                result = 0;

  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );

  /*
   *  Look for any active file descriptor entry.
   */

  for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) {

    if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {

       /*
        *  Check if this node is under the file system that we
        *  are trying to dismount.
        */ 

       if ( iop->pathinfo.mt_entry == fs_mt_entry ) {
          result = 1;
          break;
       }
    }
  }

  rtems_semaphore_release( rtems_libio_semaphore );

  return result;
}

/*
 *  rtems_libio_is_file_open
 *
 *  This routine scans the entire file descriptor table to determine if the
 *  given file refers to an active file descriptor.
 *
 *  If the given file is open a 1 is returned, otherwise a 0 is returned.
 */

int rtems_libio_is_file_open(
  void         *node_access
)
{
  rtems_libio_t     *iop;
  int                result=0; 

  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );

  /*
   *  Look for any active file descriptor entry.
   */

  for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) {

    if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {

       /*
        *  Check if this node is under the file system that we
        *  are trying to dismount.
        */ 

       if ( iop->pathinfo.node_access == node_access ) {
          result = 1;
          break;
       }
    }
  }

  rtems_semaphore_release( rtems_libio_semaphore );

  return result;
}