⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memfile.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  IMFS Device Node Handlers * *  This file contains the set of handlers used to process operations on *  IMFS memory file nodes.  The memory files are created in memory using *  malloc'ed memory.  Thus any data stored in one of these files is lost *  at system shutdown unless special arrangements to copy the data to  *  some type of non-volailte storage are made by the application. * *  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.com/license/LICENSE. * *  $Id: memfile.c,v 1.19.2.1 2003/09/04 18:47:02 joel Exp $ */#if HAVE_CONFIG_H#include "config.h"#endif#include <stdlib.h>#include <string.h>#include <assert.h>#include <errno.h>#include <rtems.h>#include <rtems/libio.h>#include "imfs.h"#include <rtems/libio_.h>#include <rtems/seterr.h>#define MEMFILE_STATIC /* *  Prototypes of private routines  */MEMFILE_STATIC int IMFS_memfile_extend(   IMFS_jnode_t  *the_jnode,   off_t          new_length);MEMFILE_STATIC int IMFS_memfile_addblock(   IMFS_jnode_t  *the_jnode,   unsigned int   block);MEMFILE_STATIC int IMFS_memfile_remove_block(   IMFS_jnode_t  *the_jnode,   unsigned int   block);MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer(   IMFS_jnode_t   *the_jnode,   unsigned int    block,   int             malloc_it);MEMFILE_STATIC ssize_t IMFS_memfile_read(   IMFS_jnode_t    *the_jnode,   off_t            start,   unsigned char   *destination,   unsigned int     length);ssize_t IMFS_memfile_write(  /* cannot be static as used in imfs_fchmod.c */   IMFS_jnode_t          *the_jnode,   off_t                  start,   const unsigned char   *source,   unsigned int           length);int  memfile_check_rmnod( IMFS_jnode_t *the_jnode );void *memfile_alloc_block(void);void memfile_free_block(  void *memory);/* *  memfile_open * *  This routine processes the open() system call.  Note that there is *  nothing special to be done at open() time. */int memfile_open(  rtems_libio_t *iop,  const char    *pathname,  unsigned32     flag,  unsigned32     mode){  IMFS_jnode_t  *the_jnode;  the_jnode = iop->file_info;  if (iop->flags & LIBIO_FLAGS_APPEND)    iop->offset = the_jnode->info.file.size;  iop->size = the_jnode->info.file.size;  return 0;}/* *  memfile_close * *  This routine processes the close() system call.  Note that there is *  nothing to flush or memory to free at this point. */int memfile_close(  rtems_libio_t *iop){  IMFS_jnode_t   *the_jnode;  the_jnode = iop->file_info;  if (iop->flags & LIBIO_FLAGS_APPEND)    iop->offset = the_jnode->info.file.size;  memfile_check_rmnod( the_jnode );  return 0;}/* *  memfile_read * *  This routine processes the read() system call. */ssize_t memfile_read(  rtems_libio_t *iop,  void          *buffer,  unsigned32     count){  IMFS_jnode_t   *the_jnode;  the_jnode = iop->file_info;  return IMFS_memfile_read( the_jnode, iop->offset, buffer, count );}/* *  memfile_write * *  This routine processes the write() system call. */ssize_t memfile_write(  rtems_libio_t *iop,  const void    *buffer,  unsigned32     count){  IMFS_jnode_t   *the_jnode;  ssize_t         status;  the_jnode = iop->file_info;  status = IMFS_memfile_write( the_jnode, iop->offset, buffer, count );  iop->size = the_jnode->info.file.size;  return status;}/* *  memfile_ioctl * *  This routine processes the ioctl() system call. * *  NOTE:  No ioctl()'s are supported for in-memory files. */int memfile_ioctl(  rtems_libio_t *iop,  unsigned32     command,  void          *buffer){  IMFS_jnode_t   *the_jnode;  the_jnode = iop->file_info;  return 0;}/* *  memfile_lseek * *  This routine processes the lseek() system call. */int memfile_lseek(  rtems_libio_t   *iop,  off_t            offset,  int              whence){  IMFS_jnode_t   *the_jnode;  the_jnode = iop->file_info;  if (the_jnode->type == IMFS_LINEAR_FILE) {    if (iop->offset > the_jnode->info.linearfile.size)      iop->offset = the_jnode->info.linearfile.size;  }  else {  /* Must be a block file (IMFS_MEMORY_FILE). */    if (IMFS_memfile_extend( the_jnode, iop->offset ))      rtems_set_errno_and_return_minus_one( ENOSPC );    iop->size = the_jnode->info.file.size;  }  return iop->offset;}/* *  memfile_stat * *  This IMFS_stat() can be used. *//* *  memfile_ftruncate * *  This routine processes the ftruncate() system call. */int memfile_ftruncate(  rtems_libio_t        *iop,  off_t                 length){  IMFS_jnode_t   *the_jnode;  the_jnode = iop->file_info;  /*   *  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 > the_jnode->info.file.size )    return IMFS_memfile_extend( the_jnode, 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.   */  the_jnode->info.file.size = length;  iop->size = the_jnode->info.file.size;  IMFS_update_atime( the_jnode );  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_jnode_t  *the_jnode,   off_t          new_length){  unsigned int   block;  unsigned int   new_blocks;  unsigned int   old_blocks;  /*   *  Perform internal consistency checks   */  assert( the_jnode );  if ( !the_jnode )    rtems_set_errno_and_return_minus_one( EIO );  assert( the_jnode->type == IMFS_MEMORY_FILE );  if ( the_jnode->type != IMFS_MEMORY_FILE )    rtems_set_errno_and_return_minus_one( EIO );  if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )    rtems_set_errno_and_return_minus_one( EINVAL );  if ( new_length <= the_jnode->info.file.size )    return 0;  /*   *  Calculate the number of range of blocks to allocate   */  new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;  old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK;  /*   *  Now allocate each of those blocks.   */  for ( block=old_blocks ; block<=new_blocks ; block++ ) {    if ( IMFS_memfile_addblock( the_jnode, block ) ) {       for ( ; block>=old_blocks ; block-- ) {          IMFS_memfile_remove_block( the_jnode, block );       }       rtems_set_errno_and_return_minus_one( ENOSPC );    }  }  /*   *  Set the new length of the file.   */  the_jnode->info.file.size = new_length;  return 0;}/* *  IMFS_memfile_addblock * *  This routine adds a single block to the specified in-memory file. */MEMFILE_STATIC int IMFS_memfile_addblock(   IMFS_jnode_t  *the_jnode,   unsigned int   block){  block_p  memory;  block_p *block_entry_ptr;  assert( the_jnode );  if ( !the_jnode )    rtems_set_errno_and_return_minus_one( EIO );  assert( the_jnode->type == IMFS_MEMORY_FILE );  if ( the_jnode->type != IMFS_MEMORY_FILE )    rtems_set_errno_and_return_minus_one( EIO );  block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 1 );  if ( *block_entry_ptr )    return 0;#if 0  printf( "%d %p", block, block_entry_ptr );    fflush(stdout);#endif  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 int IMFS_memfile_remove_block(   IMFS_jnode_t  *the_jnode,   unsigned int   block){  block_p *block_entry_ptr;  block_p  ptr;  block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );  ptr = *block_entry_ptr;  *block_entry_ptr = 0;  memfile_free_block( ptr );  return 1;}/* *  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. */void memfile_free_blocks_in_table(  block_p **block_table,  int       entries){  int      i;  block_p *b;  /*   *  Perform internal consistency checks   */  assert( block_table );  if ( !block_table )    return;  /*   *  Now go through all the slots in the table and free the memory.   */  b = *block_table;  for ( i=0 ; i<entries ; i++ ) {    if ( b[i] ) {      memfile_free_block( b[i] );      b[i] = 0;    }  }  /*   *  Now that all the blocks in the block table are free, we can    *  free the block table itself.   */  memfile_free_block( *block_table );  *block_table = 0;}/* *  IMFS_memfile_remove * *  This routine frees all memory associated with an in memory file. * *  NOTE:  This is an exceptionally conservative implementation.   *         It will check EVERY pointer which is non-NULL and insure *         any child non-NULL pointers are freed.  Optimistically, all that *         is necessary is to scan until a NULL pointer is found.  There *         should be no allocated data past that point. * *         In experimentation on the powerpc simulator, it was noted *         that using blocks which held 128 slots versus 16 slots made *         a significant difference in the performance of this routine. * *         Regardless until the IMFS implementation is proven, it *         is better to stick to simple, easy to understand algorithms. */int IMFS_memfile_remove( IMFS_jnode_t  *the_jnode){  IMFS_memfile_t  *info;  int              i;  int              j;  unsigned int     to_free;  block_p         *p;  /*   *  Perform internal consistency checks   */  assert( the_jnode );  if ( !the_jnode )    rtems_set_errno_and_return_minus_one( EIO );  assert( the_jnode->type == IMFS_MEMORY_FILE );  if ( the_jnode->type != IMFS_MEMORY_FILE )    rtems_set_errno_and_return_minus_one( EIO );  /*   *  Eventually this could be set smarter at each call to   *  memfile_free_blocks_in_table to greatly speed this up.   */  to_free = IMFS_MEMFILE_BLOCK_SLOTS;  /*   *  Now start freeing blocks in this order:   *    + indirect   *    + doubly indirect   *    + triply indirect   */  info = &the_jnode->info.file;  if ( info->indirect ) {    memfile_free_blocks_in_table( &info->indirect, to_free );  }  if ( info->doubly_indirect ) {    for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {      if ( info->doubly_indirect[i] ) {        memfile_free_blocks_in_table(         (block_p **)&info->doubly_indirect[i], to_free );      }    }    memfile_free_blocks_in_table( &info->doubly_indirect, to_free );  }    if ( info->triply_indirect ) {    for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {      p = (block_p *) info->triply_indirect[i];      if ( !p )  /* ensure we have a valid pointer */         break;      for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {        if ( p[j] ) {          memfile_free_blocks_in_table( (block_p **)&p[j], to_free);        }      }      memfile_free_blocks_in_table(        (block_p **)&info->triply_indirect[i], to_free );    }    memfile_free_blocks_in_table(        (block_p **)&info->triply_indirect, to_free );  }  return 0;}/* *  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_jnode_t    *the_jnode,   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   */  assert( the_jnode );  if ( !the_jnode )    rtems_set_errno_and_return_minus_one( EIO );  assert( the_jnode->type == IMFS_MEMORY_FILE ||

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -