From e4d35d82fc6d25ae8e1d98f14938a7208fb8a592 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 5 Feb 2015 16:43:58 +0100 Subject: IMFS: Split linfile and memfile modules Make several functions static. --- cpukit/libfs/src/imfs/imfs.h | 62 +- cpukit/libfs/src/imfs/imfs_handlers_memfile.c | 87 --- cpukit/libfs/src/imfs/imfs_linfile.c | 97 +++ cpukit/libfs/src/imfs/imfs_memfile.c | 860 +++++++++++++++++++++++++ cpukit/libfs/src/imfs/imfs_stat_file.c | 33 + cpukit/libfs/src/imfs/memfile.c | 893 -------------------------- 6 files changed, 1000 insertions(+), 1032 deletions(-) delete mode 100644 cpukit/libfs/src/imfs/imfs_handlers_memfile.c create mode 100644 cpukit/libfs/src/imfs/imfs_linfile.c create mode 100644 cpukit/libfs/src/imfs/imfs_memfile.c create mode 100644 cpukit/libfs/src/imfs/imfs_stat_file.c delete mode 100644 cpukit/libfs/src/imfs/memfile.c (limited to 'cpukit/libfs/src/imfs') diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h index f69408a443..12881c4073 100644 --- a/cpukit/libfs/src/imfs/imfs.h +++ b/cpukit/libfs/src/imfs/imfs.h @@ -511,6 +511,11 @@ extern int IMFS_stat( struct stat *buf ); +extern int IMFS_stat_file( + const rtems_filesystem_location_info_t *loc, + struct stat *buf +); + /** * @brief IMFS evaluation node support. */ @@ -711,20 +716,6 @@ extern int IMFS_unmount( rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ ); -extern void IMFS_memfile_remove( - IMFS_jnode_t *the_jnode /* IN/OUT */ -); - -/** - * @brief Truncate a memory file. - * - * This routine processes the ftruncate() system call. - */ -extern int memfile_ftruncate( - rtems_libio_t *iop, /* IN */ - off_t length /* IN */ -); - /** * @brief Read the next directory of the IMFS. * @@ -756,44 +747,11 @@ extern ssize_t imfs_dir_read( */ /**@{*/ -/** - * @brief Open a linear file. - * - * Transforms the file into a memfile if opened for writing. - */ -extern int IMFS_linfile_open( - rtems_libio_t *iop, /* IN */ - const char *pathname, /* IN */ - int oflag, /* IN */ - mode_t mode /* IN */ -); - -extern ssize_t IMFS_linfile_read( - rtems_libio_t *iop, - void *buffer, - size_t count -); - -/** - * @brief Read a memory file. - * - * This routine processes the read() system call. - */ -extern ssize_t memfile_read( - rtems_libio_t *iop, /* IN */ - void *buffer, /* IN */ - size_t count /* IN */ -); - -/** - * @brief Write a memory file. - * - * This routine processes the write() system call. - */ -extern ssize_t memfile_write( - rtems_libio_t *iop, /* IN */ - const void *buffer, /* IN */ - size_t count /* IN */ +extern ssize_t IMFS_memfile_write( + IMFS_memfile_t *memfile, + off_t start, + const unsigned char *source, + unsigned int length ); /** @} */ diff --git a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c deleted file mode 100644 index 1e5dba2a63..0000000000 --- a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file - * - * @brief Memfile Operations Tables - * @ingroup IMFS - */ - -/* - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * 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 "imfs.h" - -static int IMFS_stat_file( - const rtems_filesystem_location_info_t *loc, - struct stat *buf -) -{ - const IMFS_file_t *file = loc->node_access; - - buf->st_size = file->File.size; - buf->st_blksize = imfs_rq_memfile_bytes_per_block; - - return IMFS_stat( loc, buf ); -} - -static const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = { - .open_h = rtems_filesystem_default_open, - .close_h = rtems_filesystem_default_close, - .read_h = memfile_read, - .write_h = memfile_write, - .ioctl_h = rtems_filesystem_default_ioctl, - .lseek_h = rtems_filesystem_default_lseek_file, - .fstat_h = IMFS_stat_file, - .ftruncate_h = memfile_ftruncate, - .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success, - .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success, - .fcntl_h = rtems_filesystem_default_fcntl, - .kqfilter_h = rtems_filesystem_default_kqfilter, - .poll_h = rtems_filesystem_default_poll, - .readv_h = rtems_filesystem_default_readv, - .writev_h = rtems_filesystem_default_writev -}; - -static const rtems_filesystem_file_handlers_r IMFS_linfile_handlers = { - .open_h = IMFS_linfile_open, - .close_h = rtems_filesystem_default_close, - .read_h = IMFS_linfile_read, - .write_h = rtems_filesystem_default_write, - .ioctl_h = rtems_filesystem_default_ioctl, - .lseek_h = rtems_filesystem_default_lseek_file, - .fstat_h = IMFS_stat_file, - .ftruncate_h = rtems_filesystem_default_ftruncate, - .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success, - .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success, - .fcntl_h = rtems_filesystem_default_fcntl, - .kqfilter_h = rtems_filesystem_default_kqfilter, - .poll_h = rtems_filesystem_default_poll, - .readv_h = rtems_filesystem_default_readv, - .writev_h = rtems_filesystem_default_writev -}; - -const IMFS_mknod_control IMFS_mknod_control_memfile = { - { - .handlers = &IMFS_memfile_handlers, - .node_initialize = IMFS_node_initialize_default, - .node_remove = IMFS_node_remove_default, - .node_destroy = IMFS_memfile_remove - }, - .node_size = sizeof( IMFS_file_t ) -}; - -const IMFS_node_control IMFS_node_control_linfile = { - .handlers = &IMFS_linfile_handlers, - .node_initialize = IMFS_node_initialize_default, - .node_remove = IMFS_node_remove_default, - .node_destroy = IMFS_node_destroy_default -}; diff --git a/cpukit/libfs/src/imfs/imfs_linfile.c b/cpukit/libfs/src/imfs/imfs_linfile.c new file mode 100644 index 0000000000..8a1486600b --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_linfile.c @@ -0,0 +1,97 @@ +/** + * @file + * + * @ingroup IMFS + */ + +/* + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * 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 "imfs.h" + +static ssize_t IMFS_linfile_read( + rtems_libio_t *iop, + void *buffer, + size_t count +) +{ + IMFS_file_t *file = IMFS_iop_to_file( iop ); + off_t start = iop->offset; + size_t size = file->File.size; + const unsigned char *data = file->Linearfile.direct; + + if (count > size - start) + count = size - start; + + IMFS_update_atime( &file->Node ); + iop->offset = start + count; + memcpy(buffer, &data[start], count); + + return (ssize_t) count; +} + +static int IMFS_linfile_open( + rtems_libio_t *iop, + const char *pathname, + int oflag, + mode_t mode +) +{ + IMFS_file_t *file; + + file = iop->pathinfo.node_access; + + /* + * Perform 'copy on write' for linear files + */ + if ((iop->flags & LIBIO_FLAGS_WRITE) != 0) { + uint32_t count = file->File.size; + const unsigned char *buffer = file->Linearfile.direct; + + file->Node.control = &IMFS_mknod_control_memfile.node_control; + file->File.size = 0; + file->Memfile.indirect = 0; + file->Memfile.doubly_indirect = 0; + file->Memfile.triply_indirect = 0; + if ((count != 0) + && (IMFS_memfile_write(&file->Memfile, 0, buffer, count) == -1)) + return -1; + } + + return 0; +} + +static const rtems_filesystem_file_handlers_r IMFS_linfile_handlers = { + .open_h = IMFS_linfile_open, + .close_h = rtems_filesystem_default_close, + .read_h = IMFS_linfile_read, + .write_h = rtems_filesystem_default_write, + .ioctl_h = rtems_filesystem_default_ioctl, + .lseek_h = rtems_filesystem_default_lseek_file, + .fstat_h = IMFS_stat_file, + .ftruncate_h = rtems_filesystem_default_ftruncate, + .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success, + .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success, + .fcntl_h = rtems_filesystem_default_fcntl, + .kqfilter_h = rtems_filesystem_default_kqfilter, + .poll_h = rtems_filesystem_default_poll, + .readv_h = rtems_filesystem_default_readv, + .writev_h = rtems_filesystem_default_writev +}; + +const IMFS_node_control IMFS_node_control_linfile = { + .handlers = &IMFS_linfile_handlers, + .node_initialize = IMFS_node_initialize_default, + .node_remove = IMFS_node_remove_default, + .node_destroy = IMFS_node_destroy_default +}; diff --git a/cpukit/libfs/src/imfs/imfs_memfile.c b/cpukit/libfs/src/imfs/imfs_memfile.c new file mode 100644 index 0000000000..2b6a49698a --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_memfile.c @@ -0,0 +1,860 @@ +/** + * @file + * + * @brief IMFS Memory File Handlers + * @ingroup IMFS + */ + +/* + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * 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 "imfs.h" + +#include +#include + +/* + * Prototypes of private routines + */ +static int IMFS_memfile_extend( + IMFS_memfile_t *memfile, + bool zero_fill, + off_t new_length +); + +static int IMFS_memfile_addblock( + IMFS_memfile_t *memfile, + unsigned int block +); + +static void IMFS_memfile_remove_block( + IMFS_memfile_t *memfile, + unsigned int block +); + +static block_p *IMFS_memfile_get_block_pointer( + IMFS_memfile_t *memfile, + unsigned int block, + int malloc_it +); + +static ssize_t IMFS_memfile_read( + IMFS_file_t *file, + off_t start, + unsigned char *destination, + unsigned int length +); + +static void *memfile_alloc_block(void); + +static void memfile_free_block( + void *memory +); + +static ssize_t memfile_read( + rtems_libio_t *iop, + void *buffer, + size_t count +) +{ + IMFS_file_t *file = IMFS_iop_to_file( iop ); + ssize_t status; + + status = IMFS_memfile_read( file, iop->offset, buffer, count ); + + if ( status > 0 ) + iop->offset += status; + + return status; +} + +static ssize_t memfile_write( + rtems_libio_t *iop, + const void *buffer, + size_t count +) +{ + IMFS_memfile_t *memfile = IMFS_iop_to_memfile( iop ); + ssize_t status; + + if ((iop->flags & LIBIO_FLAGS_APPEND) != 0) + iop->offset = memfile->File.size; + + status = IMFS_memfile_write( memfile, iop->offset, buffer, count ); + + if ( status > 0 ) + iop->offset += status; + + return status; +} + +/* + * memfile_stat + * + * This IMFS_stat() can be used. + */ + +static int memfile_ftruncate( + rtems_libio_t *iop, + off_t length +) +{ + IMFS_memfile_t *memfile = IMFS_iop_to_memfile( iop ); + + /* + * POSIX 1003.1b does not specify what happens if you truncate a file + * and the new length is greater than the current size. We treat this + * as an extend operation. + */ + + if ( length > memfile->File.size ) + return IMFS_memfile_extend( memfile, true, length ); + + /* + * The in-memory files do not currently reclaim memory until the file is + * deleted. So we leave the previously allocated blocks in place for + * future use and just set the length. + */ + memfile->File.size = length; + + IMFS_mtime_ctime_update( &memfile->File.Node ); + + return 0; +} + +/* + * IMFS_memfile_extend + * + * This routine insures that the in-memory file is of the length + * specified. If necessary, it will allocate memory blocks to + * extend the file. + */ +static int IMFS_memfile_extend( + IMFS_memfile_t *memfile, + bool zero_fill, + off_t new_length +) +{ + unsigned int block; + unsigned int new_blocks; + unsigned int old_blocks; + unsigned int offset; + + /* + * Perform internal consistency checks + */ + IMFS_assert( memfile ); + + /* + * Verify new file size is supported + */ + if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE ) + rtems_set_errno_and_return_minus_one( EFBIG ); + + /* + * Verify new file size is actually larger than current size + */ + if ( new_length <= memfile->File.size ) + return 0; + + /* + * Calculate the number of range of blocks to allocate + */ + new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK; + old_blocks = memfile->File.size / IMFS_MEMFILE_BYTES_PER_BLOCK; + offset = memfile->File.size - old_blocks * IMFS_MEMFILE_BYTES_PER_BLOCK; + + /* + * Now allocate each of those blocks. + */ + for ( block=old_blocks ; block<=new_blocks ; block++ ) { + if ( !IMFS_memfile_addblock( memfile, block ) ) { + if ( zero_fill ) { + size_t count = IMFS_MEMFILE_BYTES_PER_BLOCK - offset; + block_p *block_ptr = + IMFS_memfile_get_block_pointer( memfile, block, 0 ); + + memset( &(*block_ptr) [offset], 0, count); + offset = 0; + } + } else { + for ( ; block>=old_blocks ; block-- ) { + IMFS_memfile_remove_block( memfile, block ); + } + rtems_set_errno_and_return_minus_one( ENOSPC ); + } + } + + /* + * Set the new length of the file. + */ + memfile->File.size = new_length; + + IMFS_mtime_ctime_update( &memfile->File.Node ); + + return 0; +} + +/* + * IMFS_memfile_addblock + * + * This routine adds a single block to the specified in-memory file. + */ +static int IMFS_memfile_addblock( + IMFS_memfile_t *memfile, + unsigned int block +) +{ + block_p memory; + block_p *block_entry_ptr; + + IMFS_assert( memfile ); + + /* + * Obtain the pointer for the specified block number + */ + block_entry_ptr = IMFS_memfile_get_block_pointer( memfile, block, 1 ); + if ( !block_entry_ptr ) + return 1; + + if ( *block_entry_ptr ) + return 0; + + /* + * There is no memory for this block number so allocate it. + */ + memory = memfile_alloc_block(); + if ( !memory ) + return 1; + + *block_entry_ptr = memory; + return 0; +} + +/* + * IMFS_memfile_remove_block + * + * This routine removes the specified block from the in-memory file. + * + * NOTE: This is a support routine and is called only to remove + * the last block or set of blocks in a file. Removing a + * block from the middle of a file would be exceptionally + * dangerous and the results unpredictable. + */ +static void IMFS_memfile_remove_block( + IMFS_memfile_t *memfile, + unsigned int block +) +{ + block_p *block_ptr; + block_p ptr; + + block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 ); + if ( block_ptr ) { + ptr = *block_ptr; + *block_ptr = 0; + memfile_free_block( ptr ); + } +} + +/* + * memfile_free_blocks_in_table + * + * This is a support routine for IMFS_memfile_remove. It frees all the + * blocks in one of the indirection tables. + */ +static void memfile_free_blocks_in_table( + block_p **block_table, + int entries +) +{ + int i; + block_p *b; + + /* + * Perform internal consistency checks + */ + IMFS_assert( block_table ); + + /* + * Now go through all the slots in the table and free the memory. + */ + b = *block_table; + + for ( i=0 ; iindirect ) { + memfile_free_blocks_in_table( &memfile->indirect, to_free ); + } + + if ( memfile->doubly_indirect ) { + for ( i=0 ; idoubly_indirect[i] ) { + memfile_free_blocks_in_table( + (block_p **)&memfile->doubly_indirect[i], to_free ); + } + } + memfile_free_blocks_in_table( &memfile->doubly_indirect, to_free ); + + } + + if ( memfile->triply_indirect ) { + for ( i=0 ; itriply_indirect[i]; + if ( !p ) /* ensure we have a valid pointer */ + break; + for ( j=0 ; jtriply_indirect[i], to_free ); + } + memfile_free_blocks_in_table( + (block_p **)&memfile->triply_indirect, to_free ); + } + + IMFS_node_destroy_default( the_jnode ); +} + +/* + * IMFS_memfile_read + * + * This routine read from memory file pointed to by the_jnode into + * the specified data buffer specified by destination. The file + * is NOT extended. An offset greater than the length of the file + * is considered an error. Read from an offset for more bytes than + * are between the offset and the end of the file will result in + * reading the data between offset and the end of the file (truncated + * read). + */ +static ssize_t IMFS_memfile_read( + IMFS_file_t *file, + off_t start, + unsigned char *destination, + unsigned int length +) +{ + block_p *block_ptr; + unsigned int block; + unsigned int my_length; + unsigned int to_copy = 0; + unsigned int last_byte; + unsigned int copied; + unsigned int start_offset; + unsigned char *dest; + + dest = destination; + + /* + * Perform internal consistency checks + */ + IMFS_assert( file ); + IMFS_assert( dest ); + + /* + * Linear files (as created from a tar file are easier to handle + * than block files). + */ + my_length = length; + + /* + * If the last byte we are supposed to read is past the end of this + * in memory file, then shorten the length to read. + */ + last_byte = start + length; + if ( last_byte > file->Memfile.File.size ) + my_length = file->Memfile.File.size - start; + + copied = 0; + + /* + * Three phases to the read: + * + possibly the last part of one block + * + all of zero of more blocks + * + possibly the first part of one block + */ + + /* + * Phase 1: possibly the last part of one block + */ + start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK; + block = start / IMFS_MEMFILE_BYTES_PER_BLOCK; + if ( start_offset ) { + to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset; + if ( to_copy > my_length ) + to_copy = my_length; + block_ptr = IMFS_memfile_get_block_pointer( &file->Memfile, block, 0 ); + if ( !block_ptr ) + return copied; + memcpy( dest, &(*block_ptr)[ start_offset ], to_copy ); + dest += to_copy; + block++; + my_length -= to_copy; + copied += to_copy; + } + + /* + * Phase 2: all of zero of more blocks + */ + to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK; + while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) { + block_ptr = IMFS_memfile_get_block_pointer( &file->Memfile, block, 0 ); + if ( !block_ptr ) + return copied; + memcpy( dest, &(*block_ptr)[ 0 ], to_copy ); + dest += to_copy; + block++; + my_length -= to_copy; + copied += to_copy; + } + + /* + * Phase 3: possibly the first part of one block + */ + IMFS_assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK ); + + if ( my_length ) { + block_ptr = IMFS_memfile_get_block_pointer( &file->Memfile, block, 0 ); + if ( !block_ptr ) + return copied; + memcpy( dest, &(*block_ptr)[ 0 ], my_length ); + copied += my_length; + } + + IMFS_update_atime( &file->Node ); + + return copied; +} + +/* + * IMFS_memfile_write + * + * This routine writes the specified data buffer into the in memory + * file pointed to by memfile. The file is extended as needed. + */ +ssize_t IMFS_memfile_write( + IMFS_memfile_t *memfile, + off_t start, + const unsigned char *source, + unsigned int length +) +{ + block_p *block_ptr; + unsigned int block; + int status; + unsigned int my_length; + unsigned int to_copy = 0; + unsigned int last_byte; + unsigned int start_offset; + int copied; + const unsigned char *src; + + src = source; + + /* + * Perform internal consistency checks + */ + IMFS_assert( source ); + IMFS_assert( memfile ); + + my_length = length; + /* + * If the last byte we are supposed to write is past the end of this + * in memory file, then extend the length. + */ + + last_byte = start + my_length; + if ( last_byte > memfile->File.size ) { + bool zero_fill = start > memfile->File.size; + + status = IMFS_memfile_extend( memfile, zero_fill, last_byte ); + if ( status ) + return status; + } + + copied = 0; + + /* + * Three phases to the write: + * + possibly the last part of one block + * + all of zero of more blocks + * + possibly the first part of one block + */ + + /* + * Phase 1: possibly the last part of one block + */ + start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK; + block = start / IMFS_MEMFILE_BYTES_PER_BLOCK; + if ( start_offset ) { + to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset; + if ( to_copy > my_length ) + to_copy = my_length; + block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 ); + if ( !block_ptr ) + return copied; + #if 0 + fprintf( + stderr, + "write %d at %d in %d: %*s\n", + to_copy, + start_offset, + block, + to_copy, + src + ); + #endif + memcpy( &(*block_ptr)[ start_offset ], src, to_copy ); + src += to_copy; + block++; + my_length -= to_copy; + copied += to_copy; + } + + /* + * Phase 2: all of zero of more blocks + */ + + to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK; + while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) { + block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 ); + if ( !block_ptr ) + return copied; + #if 0 + fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src ); + #endif + memcpy( &(*block_ptr)[ 0 ], src, to_copy ); + src += to_copy; + block++; + my_length -= to_copy; + copied += to_copy; + } + + /* + * Phase 3: possibly the first part of one block + */ + IMFS_assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK ); + + to_copy = my_length; + if ( my_length ) { + block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 ); + if ( !block_ptr ) + return copied; + #if 0 + fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src ); + #endif + memcpy( &(*block_ptr)[ 0 ], src, my_length ); + my_length = 0; + copied += to_copy; + } + + IMFS_mtime_ctime_update( &memfile->File.Node ); + + return copied; +} + +/* + * IMFS_memfile_get_block_pointer + * + * This routine looks up the block pointer associated with the given block + * number. If that block has not been allocated and "malloc_it" is + * TRUE, then the block is allocated. Otherwise, it is an error. + */ +#if 0 +block_p *IMFS_memfile_get_block_pointer_DEBUG( + IMFS_jnode_t *the_jnode, + unsigned int block, + int malloc_it +); + +block_p *IMFS_memfile_get_block_pointer( + IMFS_jnode_t *the_jnode, + unsigned int block, + int malloc_it +) +{ + block_p *p; + + p = IMFS_memfile_get_block_pointer_DEBUG( the_jnode, block, malloc_it ); + fprintf(stdout, "(%d -> %p) ", block, p ); + return p; +} + +block_p *IMFS_memfile_get_block_pointer_DEBUG( +#else +block_p *IMFS_memfile_get_block_pointer( +#endif + IMFS_memfile_t *memfile, + unsigned int block, + int malloc_it +) +{ + unsigned int my_block; + unsigned int singly; + unsigned int doubly; + unsigned int triply; + block_p *p; + block_p *p1; + block_p *p2; + + /* + * Perform internal consistency checks + */ + IMFS_assert( memfile ); + + my_block = block; + + /* + * Is the block number in the simple indirect portion? + */ + if ( my_block <= LAST_INDIRECT ) { + p = memfile->indirect; + + if ( malloc_it ) { + + if ( !p ) { + p = memfile_alloc_block(); + if ( !p ) + return 0; + memfile->indirect = p; + } + return &memfile->indirect[ my_block ]; + } + + if ( !p ) + return 0; + + return &memfile->indirect[ my_block ]; + } + + /* + * Is the block number in the doubly indirect portion? + */ + + if ( my_block <= LAST_DOUBLY_INDIRECT ) { + my_block -= FIRST_DOUBLY_INDIRECT; + + singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS; + doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS; + + p = memfile->doubly_indirect; + if ( malloc_it ) { + + if ( !p ) { + p = memfile_alloc_block(); + if ( !p ) + return 0; + memfile->doubly_indirect = p; + } + + p1 = (block_p *)p[ doubly ]; + if ( !p1 ) { + p1 = memfile_alloc_block(); + if ( !p1 ) + return 0; + p[ doubly ] = (block_p) p1; + } + + return (block_p *)&p1[ singly ]; + } + + if ( !p ) + return 0; + + p = (block_p *)p[ doubly ]; + if ( !p ) + return 0; + + return (block_p *)&p[ singly ]; + } + + /* + * Is the block number in the triply indirect portion? + */ + if ( my_block <= LAST_TRIPLY_INDIRECT ) { + my_block -= FIRST_TRIPLY_INDIRECT; + + singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS; + doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS; + triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS; + doubly %= IMFS_MEMFILE_BLOCK_SLOTS; + + p = memfile->triply_indirect; + + if ( malloc_it ) { + if ( !p ) { + p = memfile_alloc_block(); + if ( !p ) + return 0; + memfile->triply_indirect = p; + } + + p1 = (block_p *) p[ triply ]; + if ( !p1 ) { + p1 = memfile_alloc_block(); + if ( !p1 ) + return 0; + p[ triply ] = (block_p) p1; + } + + p2 = (block_p *)p1[ doubly ]; + if ( !p2 ) { + p2 = memfile_alloc_block(); + if ( !p2 ) + return 0; + p1[ doubly ] = (block_p) p2; + } + return (block_p *)&p2[ singly ]; + } + + if ( !p ) + return 0; + + p1 = (block_p *) p[ triply ]; + if ( !p1 ) + return 0; + + p2 = (block_p *)p1[ doubly ]; + if ( !p2 ) + return 0; + + return (block_p *)&p2[ singly ]; + } + + /* + * This means the requested block number is out of range. + */ + return 0; +} + +/* + * memfile_alloc_block + * + * Allocate a block for an in-memory file. + */ +int memfile_blocks_allocated = 0; + +void *memfile_alloc_block(void) +{ + void *memory; + + memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK); + if ( memory ) + memfile_blocks_allocated++; + + return memory; +} + +/* + * memfile_free_block + * + * Free a block from an in-memory file. + */ +void memfile_free_block( + void *memory +) +{ + free(memory); + memfile_blocks_allocated--; +} + +static const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = { + .open_h = rtems_filesystem_default_open, + .close_h = rtems_filesystem_default_close, + .read_h = memfile_read, + .write_h = memfile_write, + .ioctl_h = rtems_filesystem_default_ioctl, + .lseek_h = rtems_filesystem_default_lseek_file, + .fstat_h = IMFS_stat_file, + .ftruncate_h = memfile_ftruncate, + .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success, + .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success, + .fcntl_h = rtems_filesystem_default_fcntl, + .kqfilter_h = rtems_filesystem_default_kqfilter, + .poll_h = rtems_filesystem_default_poll, + .readv_h = rtems_filesystem_default_readv, + .writev_h = rtems_filesystem_default_writev +}; + +const IMFS_mknod_control IMFS_mknod_control_memfile = { + { + .handlers = &IMFS_memfile_handlers, + .node_initialize = IMFS_node_initialize_default, + .node_remove = IMFS_node_remove_default, + .node_destroy = IMFS_memfile_destroy + }, + .node_size = sizeof( IMFS_file_t ) +}; diff --git a/cpukit/libfs/src/imfs/imfs_stat_file.c b/cpukit/libfs/src/imfs/imfs_stat_file.c new file mode 100644 index 0000000000..2302705b2c --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_stat_file.c @@ -0,0 +1,33 @@ +/** + * @file + * + * @ingroup IMFS + */ + +/* + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * 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 "imfs.h" + +int IMFS_stat_file( + const rtems_filesystem_location_info_t *loc, + struct stat *buf +) +{ + const IMFS_file_t *file = loc->node_access; + + buf->st_size = file->File.size; + buf->st_blksize = imfs_rq_memfile_bytes_per_block; + + return IMFS_stat( loc, buf ); +} diff --git a/cpukit/libfs/src/imfs/memfile.c b/cpukit/libfs/src/imfs/memfile.c deleted file mode 100644 index 59da9a6c1b..0000000000 --- a/cpukit/libfs/src/imfs/memfile.c +++ /dev/null @@ -1,893 +0,0 @@ -/** - * @file - * - * @brief IMFS Memory File Handlers - * @ingroup IMFS - */ - -/* - * COPYRIGHT (c) 1989-2010. - * On-Line Applications Research Corporation (OAR). - * - * 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 "imfs.h" - -#include -#include - -#define MEMFILE_STATIC - -/* - * Prototypes of private routines - */ -MEMFILE_STATIC int IMFS_memfile_extend( - IMFS_memfile_t *memfile, - bool zero_fill, - off_t new_length -); - -MEMFILE_STATIC int IMFS_memfile_addblock( - IMFS_memfile_t *memfile, - unsigned int block -); - -MEMFILE_STATIC void IMFS_memfile_remove_block( - IMFS_memfile_t *memfile, - unsigned int block -); - -MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer( - IMFS_memfile_t *memfile, - unsigned int block, - int malloc_it -); - -MEMFILE_STATIC ssize_t IMFS_memfile_read( - IMFS_file_t *file, - off_t start, - unsigned char *destination, - unsigned int length -); - -ssize_t IMFS_memfile_write( /* cannot be static as used in imfs_fchmod.c */ - IMFS_memfile_t *memfile, - off_t start, - const unsigned char *source, - unsigned int length -); - -void *memfile_alloc_block(void); - -void memfile_free_block( - void *memory -); - -int IMFS_linfile_open( - rtems_libio_t *iop, - const char *pathname, - int oflag, - mode_t mode -) -{ - IMFS_file_t *file; - - file = iop->pathinfo.node_access; - - /* - * Perform 'copy on write' for linear files - */ - if ((iop->flags & LIBIO_FLAGS_WRITE) != 0) { - uint32_t count = file->File.size; - const unsigned char *buffer = file->Linearfile.direct; - - file->Node.control = &IMFS_mknod_control_memfile.node_control; - file->File.size = 0; - file->Memfile.indirect = 0; - file->Memfile.doubly_indirect = 0; - file->Memfile.triply_indirect = 0; - if ((count != 0) - && (IMFS_memfile_write(&file->Memfile, 0, buffer, count) == -1)) - return -1; - } - - return 0; -} - -ssize_t IMFS_linfile_read( - rtems_libio_t *iop, - void *buffer, - size_t count -) -{ - IMFS_file_t *file = IMFS_iop_to_file( iop ); - off_t start = iop->offset; - size_t size = file->File.size; - const unsigned char *data = file->Linearfile.direct; - - if (count > size - start) - count = size - start; - - IMFS_update_atime( &file->Node ); - iop->offset = start + count; - memcpy(buffer, &data[start], count); - - return (ssize_t) count; -} - -ssize_t memfile_read( - rtems_libio_t *iop, - void *buffer, - size_t count -) -{ - IMFS_file_t *file = IMFS_iop_to_file( iop ); - ssize_t status; - - status = IMFS_memfile_read( file, iop->offset, buffer, count ); - - if ( status > 0 ) - iop->offset += status; - - return status; -} - -ssize_t memfile_write( - rtems_libio_t *iop, - const void *buffer, - size_t count -) -{ - IMFS_memfile_t *memfile = IMFS_iop_to_memfile( iop ); - ssize_t status; - - if ((iop->flags & LIBIO_FLAGS_APPEND) != 0) - iop->offset = memfile->File.size; - - status = IMFS_memfile_write( memfile, iop->offset, buffer, count ); - - if ( status > 0 ) - iop->offset += status; - - return status; -} - -/* - * memfile_stat - * - * This IMFS_stat() can be used. - */ - -int memfile_ftruncate( - rtems_libio_t *iop, - off_t length -) -{ - IMFS_memfile_t *memfile = IMFS_iop_to_memfile( iop ); - - /* - * POSIX 1003.1b does not specify what happens if you truncate a file - * and the new length is greater than the current size. We treat this - * as an extend operation. - */ - - if ( length > memfile->File.size ) - return IMFS_memfile_extend( memfile, true, length ); - - /* - * The in-memory files do not currently reclaim memory until the file is - * deleted. So we leave the previously allocated blocks in place for - * future use and just set the length. - */ - memfile->File.size = length; - - IMFS_mtime_ctime_update( &memfile->File.Node ); - - return 0; -} - -/* - * IMFS_memfile_extend - * - * This routine insures that the in-memory file is of the length - * specified. If necessary, it will allocate memory blocks to - * extend the file. - */ -MEMFILE_STATIC int IMFS_memfile_extend( - IMFS_memfile_t *memfile, - bool zero_fill, - off_t new_length -) -{ - unsigned int block; - unsigned int new_blocks; - unsigned int old_blocks; - unsigned int offset; - - /* - * Perform internal consistency checks - */ - IMFS_assert( memfile ); - - /* - * Verify new file size is supported - */ - if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE ) - rtems_set_errno_and_return_minus_one( EFBIG ); - - /* - * Verify new file size is actually larger than current size - */ - if ( new_length <= memfile->File.size ) - return 0; - - /* - * Calculate the number of range of blocks to allocate - */ - new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK; - old_blocks = memfile->File.size / IMFS_MEMFILE_BYTES_PER_BLOCK; - offset = memfile->File.size - old_blocks * IMFS_MEMFILE_BYTES_PER_BLOCK; - - /* - * Now allocate each of those blocks. - */ - for ( block=old_blocks ; block<=new_blocks ; block++ ) { - if ( !IMFS_memfile_addblock( memfile, block ) ) { - if ( zero_fill ) { - size_t count = IMFS_MEMFILE_BYTES_PER_BLOCK - offset; - block_p *block_ptr = - IMFS_memfile_get_block_pointer( memfile, block, 0 ); - - memset( &(*block_ptr) [offset], 0, count); - offset = 0; - } - } else { - for ( ; block>=old_blocks ; block-- ) { - IMFS_memfile_remove_block( memfile, block ); - } - rtems_set_errno_and_return_minus_one( ENOSPC ); - } - } - - /* - * Set the new length of the file. - */ - memfile->File.size = new_length; - - IMFS_mtime_ctime_update( &memfile->File.Node ); - - return 0; -} - -/* - * IMFS_memfile_addblock - * - * This routine adds a single block to the specified in-memory file. - */ -MEMFILE_STATIC int IMFS_memfile_addblock( - IMFS_memfile_t *memfile, - unsigned int block -) -{ - block_p memory; - block_p *block_entry_ptr; - - IMFS_assert( memfile ); - - /* - * Obtain the pointer for the specified block number - */ - block_entry_ptr = IMFS_memfile_get_block_pointer( memfile, block, 1 ); - if ( !block_entry_ptr ) - return 1; - - if ( *block_entry_ptr ) - return 0; - - /* - * There is no memory for this block number so allocate it. - */ - memory = memfile_alloc_block(); - if ( !memory ) - return 1; - - *block_entry_ptr = memory; - return 0; -} - -/* - * IMFS_memfile_remove_block - * - * This routine removes the specified block from the in-memory file. - * - * NOTE: This is a support routine and is called only to remove - * the last block or set of blocks in a file. Removing a - * block from the middle of a file would be exceptionally - * dangerous and the results unpredictable. - */ -MEMFILE_STATIC void IMFS_memfile_remove_block( - IMFS_memfile_t *memfile, - unsigned int block -) -{ - block_p *block_ptr; - block_p ptr; - - block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 ); - if ( block_ptr ) { - ptr = *block_ptr; - *block_ptr = 0; - memfile_free_block( ptr ); - } -} - -/* - * memfile_free_blocks_in_table - * - * This is a support routine for IMFS_memfile_remove. It frees all the - * blocks in one of the indirection tables. - */ -static void memfile_free_blocks_in_table( - block_p **block_table, - int entries -) -{ - int i; - block_p *b; - - /* - * Perform internal consistency checks - */ - IMFS_assert( block_table ); - - /* - * Now go through all the slots in the table and free the memory. - */ - b = *block_table; - - for ( i=0 ; iindirect ) { - memfile_free_blocks_in_table( &memfile->indirect, to_free ); - } - - if ( memfile->doubly_indirect ) { - for ( i=0 ; idoubly_indirect[i] ) { - memfile_free_blocks_in_table( - (block_p **)&memfile->doubly_indirect[i], to_free ); - } - } - memfile_free_blocks_in_table( &memfile->doubly_indirect, to_free ); - - } - - if ( memfile->triply_indirect ) { - for ( i=0 ; itriply_indirect[i]; - if ( !p ) /* ensure we have a valid pointer */ - break; - for ( j=0 ; jtriply_indirect[i], to_free ); - } - memfile_free_blocks_in_table( - (block_p **)&memfile->triply_indirect, to_free ); - } - - IMFS_node_destroy_default( the_jnode ); -} - -/* - * IMFS_memfile_read - * - * This routine read from memory file pointed to by the_jnode into - * the specified data buffer specified by destination. The file - * is NOT extended. An offset greater than the length of the file - * is considered an error. Read from an offset for more bytes than - * are between the offset and the end of the file will result in - * reading the data between offset and the end of the file (truncated - * read). - */ -MEMFILE_STATIC ssize_t IMFS_memfile_read( - IMFS_file_t *file, - off_t start, - unsigned char *destination, - unsigned int length -) -{ - block_p *block_ptr; - unsigned int block; - unsigned int my_length; - unsigned int to_copy = 0; - unsigned int last_byte; - unsigned int copied; - unsigned int start_offset; - unsigned char *dest; - - dest = destination; - - /* - * Perform internal consistency checks - */ - IMFS_assert( file ); - IMFS_assert( dest ); - - /* - * Linear files (as created from a tar file are easier to handle - * than block files). - */ - my_length = length; - - /* - * If the last byte we are supposed to read is past the end of this - * in memory file, then shorten the length to read. - */ - last_byte = start + length; - if ( last_byte > file->Memfile.File.size ) - my_length = file->Memfile.File.size - start; - - copied = 0; - - /* - * Three phases to the read: - * + possibly the last part of one block - * + all of zero of more blocks - * + possibly the first part of one block - */ - - /* - * Phase 1: possibly the last part of one block - */ - start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK; - block = start / IMFS_MEMFILE_BYTES_PER_BLOCK; - if ( start_offset ) { - to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset; - if ( to_copy > my_length ) - to_copy = my_length; - block_ptr = IMFS_memfile_get_block_pointer( &file->Memfile, block, 0 ); - if ( !block_ptr ) - return copied; - memcpy( dest, &(*block_ptr)[ start_offset ], to_copy ); - dest += to_copy; - block++; - my_length -= to_copy; - copied += to_copy; - } - - /* - * Phase 2: all of zero of more blocks - */ - to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK; - while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) { - block_ptr = IMFS_memfile_get_block_pointer( &file->Memfile, block, 0 ); - if ( !block_ptr ) - return copied; - memcpy( dest, &(*block_ptr)[ 0 ], to_copy ); - dest += to_copy; - block++; - my_length -= to_copy; - copied += to_copy; - } - - /* - * Phase 3: possibly the first part of one block - */ - IMFS_assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK ); - - if ( my_length ) { - block_ptr = IMFS_memfile_get_block_pointer( &file->Memfile, block, 0 ); - if ( !block_ptr ) - return copied; - memcpy( dest, &(*block_ptr)[ 0 ], my_length ); - copied += my_length; - } - - IMFS_update_atime( &file->Node ); - - return copied; -} - -/* - * IMFS_memfile_write - * - * This routine writes the specified data buffer into the in memory - * file pointed to by memfile. The file is extended as needed. - */ -MEMFILE_STATIC ssize_t IMFS_memfile_write( - IMFS_memfile_t *memfile, - off_t start, - const unsigned char *source, - unsigned int length -) -{ - block_p *block_ptr; - unsigned int block; - int status; - unsigned int my_length; - unsigned int to_copy = 0; - unsigned int last_byte; - unsigned int start_offset; - int copied; - const unsigned char *src; - - src = source; - - /* - * Perform internal consistency checks - */ - IMFS_assert( source ); - IMFS_assert( memfile ); - - my_length = length; - /* - * If the last byte we are supposed to write is past the end of this - * in memory file, then extend the length. - */ - - last_byte = start + my_length; - if ( last_byte > memfile->File.size ) { - bool zero_fill = start > memfile->File.size; - - status = IMFS_memfile_extend( memfile, zero_fill, last_byte ); - if ( status ) - return status; - } - - copied = 0; - - /* - * Three phases to the write: - * + possibly the last part of one block - * + all of zero of more blocks - * + possibly the first part of one block - */ - - /* - * Phase 1: possibly the last part of one block - */ - start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK; - block = start / IMFS_MEMFILE_BYTES_PER_BLOCK; - if ( start_offset ) { - to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset; - if ( to_copy > my_length ) - to_copy = my_length; - block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 ); - if ( !block_ptr ) - return copied; - #if 0 - fprintf( - stderr, - "write %d at %d in %d: %*s\n", - to_copy, - start_offset, - block, - to_copy, - src - ); - #endif - memcpy( &(*block_ptr)[ start_offset ], src, to_copy ); - src += to_copy; - block++; - my_length -= to_copy; - copied += to_copy; - } - - /* - * Phase 2: all of zero of more blocks - */ - - to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK; - while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) { - block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 ); - if ( !block_ptr ) - return copied; - #if 0 - fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src ); - #endif - memcpy( &(*block_ptr)[ 0 ], src, to_copy ); - src += to_copy; - block++; - my_length -= to_copy; - copied += to_copy; - } - - /* - * Phase 3: possibly the first part of one block - */ - IMFS_assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK ); - - to_copy = my_length; - if ( my_length ) { - block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 ); - if ( !block_ptr ) - return copied; - #if 0 - fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src ); - #endif - memcpy( &(*block_ptr)[ 0 ], src, my_length ); - my_length = 0; - copied += to_copy; - } - - IMFS_mtime_ctime_update( &memfile->File.Node ); - - return copied; -} - -/* - * IMFS_memfile_get_block_pointer - * - * This routine looks up the block pointer associated with the given block - * number. If that block has not been allocated and "malloc_it" is - * TRUE, then the block is allocated. Otherwise, it is an error. - */ -#if 0 -block_p *IMFS_memfile_get_block_pointer_DEBUG( - IMFS_jnode_t *the_jnode, - unsigned int block, - int malloc_it -); - -block_p *IMFS_memfile_get_block_pointer( - IMFS_jnode_t *the_jnode, - unsigned int block, - int malloc_it -) -{ - block_p *p; - - p = IMFS_memfile_get_block_pointer_DEBUG( the_jnode, block, malloc_it ); - fprintf(stdout, "(%d -> %p) ", block, p ); - return p; -} - -block_p *IMFS_memfile_get_block_pointer_DEBUG( -#else -block_p *IMFS_memfile_get_block_pointer( -#endif - IMFS_memfile_t *memfile, - unsigned int block, - int malloc_it -) -{ - unsigned int my_block; - unsigned int singly; - unsigned int doubly; - unsigned int triply; - block_p *p; - block_p *p1; - block_p *p2; - - /* - * Perform internal consistency checks - */ - IMFS_assert( memfile ); - - my_block = block; - - /* - * Is the block number in the simple indirect portion? - */ - if ( my_block <= LAST_INDIRECT ) { - p = memfile->indirect; - - if ( malloc_it ) { - - if ( !p ) { - p = memfile_alloc_block(); - if ( !p ) - return 0; - memfile->indirect = p; - } - return &memfile->indirect[ my_block ]; - } - - if ( !p ) - return 0; - - return &memfile->indirect[ my_block ]; - } - - /* - * Is the block number in the doubly indirect portion? - */ - - if ( my_block <= LAST_DOUBLY_INDIRECT ) { - my_block -= FIRST_DOUBLY_INDIRECT; - - singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS; - doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS; - - p = memfile->doubly_indirect; - if ( malloc_it ) { - - if ( !p ) { - p = memfile_alloc_block(); - if ( !p ) - return 0; - memfile->doubly_indirect = p; - } - - p1 = (block_p *)p[ doubly ]; - if ( !p1 ) { - p1 = memfile_alloc_block(); - if ( !p1 ) - return 0; - p[ doubly ] = (block_p) p1; - } - - return (block_p *)&p1[ singly ]; - } - - if ( !p ) - return 0; - - p = (block_p *)p[ doubly ]; - if ( !p ) - return 0; - - return (block_p *)&p[ singly ]; - } - - /* - * Is the block number in the triply indirect portion? - */ - if ( my_block <= LAST_TRIPLY_INDIRECT ) { - my_block -= FIRST_TRIPLY_INDIRECT; - - singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS; - doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS; - triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS; - doubly %= IMFS_MEMFILE_BLOCK_SLOTS; - - p = memfile->triply_indirect; - - if ( malloc_it ) { - if ( !p ) { - p = memfile_alloc_block(); - if ( !p ) - return 0; - memfile->triply_indirect = p; - } - - p1 = (block_p *) p[ triply ]; - if ( !p1 ) { - p1 = memfile_alloc_block(); - if ( !p1 ) - return 0; - p[ triply ] = (block_p) p1; - } - - p2 = (block_p *)p1[ doubly ]; - if ( !p2 ) { - p2 = memfile_alloc_block(); - if ( !p2 ) - return 0; - p1[ doubly ] = (block_p) p2; - } - return (block_p *)&p2[ singly ]; - } - - if ( !p ) - return 0; - - p1 = (block_p *) p[ triply ]; - if ( !p1 ) - return 0; - - p2 = (block_p *)p1[ doubly ]; - if ( !p2 ) - return 0; - - return (block_p *)&p2[ singly ]; - } - - /* - * This means the requested block number is out of range. - */ - return 0; -} - -/* - * memfile_alloc_block - * - * Allocate a block for an in-memory file. - */ -int memfile_blocks_allocated = 0; - -void *memfile_alloc_block(void) -{ - void *memory; - - memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK); - if ( memory ) - memfile_blocks_allocated++; - - return memory; -} - -/* - * memfile_free_block - * - * Free a block from an in-memory file. - */ -void memfile_free_block( - void *memory -) -{ - free(memory); - memfile_blocks_allocated--; -} -- cgit v1.2.3