forked from Imagelibrary/rtems
This helps to detect * double insert, append, prepend errors, and * get from empty chain errors.
172 lines
3.7 KiB
C
172 lines
3.7 KiB
C
/*
|
|
* 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.
|
|
*/
|
|
|
|
#if 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 );
|
|
}
|