summaryrefslogblamecommitdiffstats
path: root/cpukit/libcsupport/src/mount-mgr.c
blob: 065c2d5d69420b5c527f7385ee8e36525b8df26b (plain) (tree)
1
2
3
4
5
6
7
8
9
10







                                                                              

                                            

                                                           
                                         

   
                    











                         


                         



                                 
 
                                                  
 
                              

                                       

 
                                                 

                                                                            
                    
 

                                                  
                  

   


                       

                                                   


                                                            
 
                                                    
     
                         
   

              

 





                                                                          
 


                                               
                 



                                 
   

 


                                   

 









                                                  

 





                                        
                                                 

                                                          
                                            
                                                     

                    
                                                   
 
                                        




                                                             
                                              
                                                        







                                                   


           




                            
                                                 







                                                   

                                        




                                                    
                                              



                           

     

                       

                                                 
/*
 *  mount()
 *
 *  Mange the mount table. You can iterate on mounts and file systems, as well
 *  as add and remove file systems not in the file system confiration table.
 *
 *  COPYRIGHT (c) Chris Johns <chrisj@rtems.org> 2010.
 *
 *  Copyright (c) 2010 embedded brains GmbH.
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.org/license/LICENSE.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <rtems/chain.h>
#include <rtems/seterr.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include <rtems/libio_.h>

typedef struct {
  rtems_chain_node node;
  rtems_filesystem_table_t entry;
} filesystem_node;

static RTEMS_CHAIN_DEFINE_EMPTY(filesystem_chain);

bool rtems_filesystem_iterate(
  rtems_per_filesystem_routine routine,
  void *routine_arg
)
{
  rtems_chain_control *chain = &filesystem_chain;
  const rtems_filesystem_table_t *table_entry = &rtems_filesystem_table [0];
  rtems_chain_node *node = NULL;
  bool stop = false;

  while ( table_entry->type && !stop ) {
    stop = (*routine)( table_entry, routine_arg );
    ++table_entry;
  }

  if ( !stop ) {
    rtems_libio_lock();
    for (
      node = rtems_chain_first( chain );
      !rtems_chain_is_tail( chain, node ) && !stop;
      node = rtems_chain_next( node )
    ) {
      const filesystem_node *fsn = (filesystem_node *) node;

      stop = (*routine)( &fsn->entry, routine_arg );
    }
    rtems_libio_unlock();
  }

  return stop;
}

typedef struct {
  const char *type;
  rtems_filesystem_fsmount_me_t mount_h;
} find_arg;

static bool find_handler(const rtems_filesystem_table_t *entry, void *arg)
{
  find_arg *fa = arg;

  if ( strcmp( entry->type, fa->type ) != 0 ) {
    return false;
  } else {
    fa->mount_h = entry->mount_h;

    return true;
  }
}

rtems_filesystem_fsmount_me_t
rtems_filesystem_get_mount_handler(
  const char *type
)
{
  find_arg fa = {
    .type = type,
    .mount_h = NULL
  };

  if ( type != NULL ) {
    rtems_filesystem_iterate( find_handler, &fa );
  }

  return fa.mount_h;
}

int
rtems_filesystem_register(
  const char                    *type,
  rtems_filesystem_fsmount_me_t  mount_h
)
{
  rtems_chain_control *chain = &filesystem_chain;
  size_t type_size = strlen(type) + 1;
  size_t fsn_size = sizeof( filesystem_node ) + type_size;
  filesystem_node *fsn = malloc( fsn_size );
  char *type_storage = (char *) fsn + sizeof( *fsn );

  if ( fsn == NULL )
    rtems_set_errno_and_return_minus_one( ENOMEM );

  memcpy(type_storage, type, type_size);
  fsn->entry.type = type_storage;
  fsn->entry.mount_h = mount_h;

  rtems_libio_lock();
  if ( rtems_filesystem_get_mount_handler( type ) == NULL ) {
    rtems_chain_initialize_node( &fsn->node );
    rtems_chain_append_unprotected( chain, &fsn->node );
  } else {
    rtems_libio_unlock();
    free( fsn );

    rtems_set_errno_and_return_minus_one( EINVAL );
  }
  rtems_libio_unlock();

  return 0;
}

int
rtems_filesystem_unregister(
  const char *type
)
{
  rtems_chain_control *chain = &filesystem_chain;
  rtems_chain_node *node = NULL;

  if ( type == NULL ) {
    rtems_set_errno_and_return_minus_one( EINVAL );
  }

  rtems_libio_lock();
  for (
    node = rtems_chain_first( chain );
    !rtems_chain_is_tail( chain, node );
    node = rtems_chain_next( node )
  ) {
    filesystem_node *fsn = (filesystem_node *) node;

    if ( strcmp( fsn->entry.type, type ) == 0 ) {
      rtems_chain_extract_unprotected( node );
      free( fsn );
      rtems_libio_unlock();

      return 0;
    }
  }
  rtems_libio_unlock();

  rtems_set_errno_and_return_minus_one( ENOENT );
}