1 //==========================================================================
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: nickg
46 // Purpose: RAM file system
47 // Description: This is a RAM filesystem for eCos. It attempts to
48 // provide full POSIX-compatible filesystem behaviour
49 // while at the same time being efficient in terms of
50 // time and space used.
53 //####DESCRIPTIONEND####
55 //==========================================================================
57 // General Description
58 // ===================
60 // This is an implementation of a RAM filesystem for eCos. Its goal is
61 // to provide a working example of a filesystem that provides most of
62 // the required POSIX functionality. And obviously it may also be
63 // useful in its own right.
69 // All files and directories are represented by node objects. Each
70 // ramfs_node structure contains the following fields:
72 // mode - Node type, file or directory.
73 // refcnt - Number of references to this node. For files each open counts as
74 // a reference and for directories a node is referenced when it is made
75 // current directory, or is opened for reading.
76 // nlink - Number of links to this node. Each directory entry that references
77 // this node is a link.
78 // size - Size of the data in this node in bytes.
79 // atime - Last time this node was accessed.
80 // mtime - Last time the data in this node was modified.
81 // ctime - Last time the status information in this node was changed.
83 // The data storage in a node is controlled by the configuration and
84 // can take two forms. These will be described later.
89 // A directory is a node whose data is a list of directory entries. To
90 // simplify management of these, long directory entries are split into
91 // a chain of fixed size ramfs_dirent structures. These contain the
94 // node - Pointer to node referenced by this entry. This is present in
95 // every directory entry fragment
96 // inuse - Set to 1 if this entry is in use, zero if it is free.
97 // first - Set to 1 if this is the first fragment of a directory entry.
98 // last - Set to 1 if this is the last fragment of a directory entry.
99 // namelen - The size of the whole file name.
100 // fraglen - The number of bytes of the file name that are stored in this
102 // next - The offset of the next fragment of this directory entry.
103 // name - The characters of the fragment of the file name stored in this
106 // Small file names are stored in a single fragment. Longer names are
107 // stored in a chain of fragments.
112 // Two data storage mechanisms may be configured, the SIMPLE and the
113 // BLOCKS mechanisms.
115 // SIMPLE Data Storage
116 // ~~~~~~~~~~~~~~~~~~~
118 // This mechanism simply uses malloc() and free() to allocate the
119 // memory for both nodes and file data. File data is stored in a
120 // single malloced vector that is realloced as necessary to acquire
123 // The advantage of this approach is that the RAM filesystem only uses
124 // as much memory as it needs, the rest is available for use by other
125 // components. It also requires much simpler data structures and code
126 // in the filesystem to manage. However, if any files get to be a
127 // significant proportion of the size of the heap, there is the danger
128 // that fragmentation will prevent any further extension of some
129 // files, even if there is enough memory in total. It also requires an
130 // implementation of malloc() to be present. If this needs to be
131 // present for other components,then this is not a significant
132 // overhead, but including it just for use by this filesystem
133 // represents a major addition of code and data structures.
136 // BLOCKS Data Storage
137 // ~~~~~~~~~~~~~~~~~~~
139 // This mechanism divides the memory used for file storage into fixed
140 // sized blocks. These blocks may either be allocated using
141 // malloc()/free(), or may be obtained from a array of blocks reserved
142 // for the purpose. Configuration allows the block size to be
143 // selected, as well as the allocation mechanism, and in the case of a
144 // block array, whether it is defined here or by an external
147 // Data storage in nodes is arranges in three arrays of pointers to
148 // blocks. The first array points directly to data blocks, the second
149 // to blocks which themselves contain pointers to data blocks, and the
150 // third to blocks which contain pointers to blocks which contain
151 // pointers to data blocks. In the default configuration These last
152 // two arrays have only one element each.
154 // The following shows how the data is arranged in a fully populated
155 // file with a 256 byte block size using the default configuration.
162 // | *------+--------> data block 0
164 // | *------+--------> data block 1
166 // | *------+--------> data block 2
168 // | *------+--------> data block 3
170 // | *------+--------> data block 4
172 // | *------+--------> data block 5
174 // | *------+--------> data block 6
176 // | *------+--------> data block 7
178 // | *------+--------> +------------+
179 // +------------+ | *------+--------> data block 8
180 // | *------+----+ +------------+
181 // +------------+ | | |
185 // | | *------+--------> data block 71
188 // +---->+------------+ +------------+
189 // | *------+-------->| *------+---->data block 72
190 // +------------+ +------------+
194 // +------------+ +------------+
195 // | *------+---+ | *------+----> data block 135
196 // +------------+ | +------------+
199 // +---->| *------+----> data block 4104
205 // | *------+----> data block 4167
210 // The advantages of this approach are that, first, memory usage is
211 // divided into discreet fixed size blocks which are easier to
212 // manage. When using malloc() to allocate them, they will fit into
213 // any free memory of at least the right size. Using the block array
214 // option removes the need to have a malloc() implementation at all.
216 // The disadvantages of this mechanism are that, first, when using
217 // malloc() to allocate blocks, the per-block memory allocator
218 // overhead is paid for each block, rather than per file. This may
219 // result in less memory overall being available for data
220 // storage. When using the block array, it is permanently reserved for
221 // use by the ram filesystem, and is not available for use by other
224 //==========================================================================
226 #include <pkgconf/system.h>
227 #include <pkgconf/hal.h>
228 #include <pkgconf/kernel.h>
229 #include <pkgconf/io_fileio.h>
230 #include <pkgconf/fs_ram.h>
232 #include <cyg/kernel/ktypes.h> // base kernel types
233 #include <cyg/infra/cyg_trac.h> // tracing macros
234 #include <cyg/infra/cyg_ass.h> // assertion macros
237 #include <sys/types.h>
239 #include <sys/stat.h>
246 #include <cyg/fileio/fileio.h>
248 #include <cyg/kernel/kapi.h>
249 #include <cyg/infra/diag.h>
251 //==========================================================================
252 // Sizes derived from configuration
254 // -------------------------------------------------------------------------
255 // Simple malloc based allocator parameters
257 #ifdef CYGPKG_FS_RAM_SIMPLE
259 #define RAMFS_FILESIZE_MAX UINT_MAX
263 // -------------------------------------------------------------------------
264 // Block allocator parameters
266 // The number of nodes per block
267 #define RAMFS_NODES_PER_BLOCK (CYGNUM_RAMFS_BLOCK_SIZE/sizeof(ramfs_node))
269 // The number of indirect pointers that can be stored in a single data block
270 #define RAMFS_INDIRECT_PER_BLOCK (CYGNUM_RAMFS_BLOCK_SIZE/sizeof(ramfs_block *))
272 // The number of directory entries that can be stored in a single data block
273 #define RAMFS_DIRENT_PER_BLOCK (CYGNUM_RAMFS_BLOCK_SIZE/sizeof(ramfs_dirent))
275 // Number of bytes contained in a one level indirect block
276 #define RAMFS_INDIRECT1_BLOCK_EXTENT (RAMFS_INDIRECT_PER_BLOCK* \
277 CYGNUM_RAMFS_BLOCK_SIZE)
279 // number of bytes contained in a two level indirect block
280 #define RAMFS_INDIRECT2_BLOCK_EXTENT (RAMFS_INDIRECT_PER_BLOCK* \
281 RAMFS_INDIRECT_PER_BLOCK* \
282 CYGNUM_RAMFS_BLOCK_SIZE)
284 // The maximum data offset for data directly accessed from the node
285 #define RAMFS_DIRECT_MAX (CYGNUM_RAMFS_BLOCKS_DIRECT*CYGNUM_RAMFS_BLOCK_SIZE)
287 // The maximum data offset for data accessed from the single level indirect blocks
288 #define RAMFS_INDIRECT1_MAX (RAMFS_DIRECT_MAX+ \
289 (CYGNUM_RAMFS_BLOCKS_INDIRECT1* \
290 RAMFS_INDIRECT1_BLOCK_EXTENT))
292 // The maximum data offset for data accessed from the two level indirect blocks
293 #define RAMFS_INDIRECT2_MAX (RAMFS_INDIRECT1_MAX+ \
294 (CYGNUM_RAMFS_BLOCKS_INDIRECT2* \
295 RAMFS_INDIRECT2_BLOCK_EXTENT))
297 // The maximum size of a file
298 #define RAMFS_FILESIZE_MAX RAMFS_INDIRECT2_MAX
302 //==========================================================================
303 // Forward definitions
305 // Filesystem operations
306 static int ramfs_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte );
307 static int ramfs_umount ( cyg_mtab_entry *mte );
308 static int ramfs_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
309 int mode, cyg_file *fte );
310 static int ramfs_unlink ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
311 static int ramfs_mkdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
312 static int ramfs_rmdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
313 static int ramfs_rename ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
314 cyg_dir dir2, const char *name2 );
315 static int ramfs_link ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
316 cyg_dir dir2, const char *name2, int type );
317 static int ramfs_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
319 static int ramfs_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
321 static int ramfs_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
323 static int ramfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
324 int key, void *buf, int len );
325 static int ramfs_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
326 int key, void *buf, int len );
329 static int ramfs_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
330 static int ramfs_fo_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
331 static int ramfs_fo_lseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
332 static int ramfs_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
334 static int ramfs_fo_fsync (struct CYG_FILE_TAG *fp, int mode );
335 static int ramfs_fo_close (struct CYG_FILE_TAG *fp);
336 static int ramfs_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf );
337 static int ramfs_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
338 static int ramfs_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
340 // Directory operations
341 static int ramfs_fo_dirread (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
342 static int ramfs_fo_dirlseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
345 //==========================================================================
346 // Filesystem table entries
348 // -------------------------------------------------------------------------
350 // This defines the entry in the filesystem table.
351 // For simplicity we use _FILESYSTEM synchronization for all accesses since
352 // we should never block in any filesystem operations.
354 FSTAB_ENTRY( ramfs_fste, "ramfs", 0,
355 CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,
370 // -------------------------------------------------------------------------
372 // This set of file operations are used for normal open files.
374 static cyg_fileops ramfs_fileops =
388 // -------------------------------------------------------------------------
389 // Directory file operations.
390 // This set of operations are used for open directories. Most entries
391 // point to error-returning stub functions. Only the read, lseek and
392 // close entries are functional.
394 static cyg_fileops ramfs_dirops =
397 (cyg_fileop_write *)cyg_fileio_enosys,
399 (cyg_fileop_ioctl *)cyg_fileio_enosys,
401 (cyg_fileop_fsync *)cyg_fileio_enosys,
403 (cyg_fileop_fstat *)cyg_fileio_enosys,
404 (cyg_fileop_getinfo *)cyg_fileio_enosys,
405 (cyg_fileop_setinfo *)cyg_fileio_enosys
408 //==========================================================================
410 // Some forward typedefs for the main data structures.
413 typedef struct ramfs_node ramfs_node;
416 typedef struct ramfs_dirent ramfs_dirent;
418 #ifndef CYGPKG_FS_RAM_SIMPLE
420 typedef cyg_uint8 ramfs_block[CYGNUM_RAMFS_BLOCK_SIZE];
424 //==========================================================================
425 // File and directory node
426 // This data structure represents a file or directory.
430 mode_t mode; // node type
431 cyg_ucount32 refcnt; // open file/current dir references
432 nlink_t nlink; // number of links to this node
433 size_t size; // size of file in bytes
434 time_t atime; // last access time
435 time_t mtime; // last modified time
436 time_t ctime; // last changed status time
438 #ifdef CYGPKG_FS_RAM_SIMPLE
440 // The data storage in this case consists of a single
441 // malloced memory block, together with its size.
443 size_t datasize; // size of data block
444 cyg_uint8 *data; // malloced data buffer
448 // The data storage in this case consists of arrays of pointers
451 #if CYGNUM_RAMFS_BLOCKS_DIRECT > 0
452 // Directly accessible blocks from the inode.
453 ramfs_block *direct[CYGNUM_RAMFS_BLOCKS_DIRECT];
455 #if CYGNUM_RAMFS_BLOCKS_INDIRECT1 > 0
456 // Single level indirection
457 ramfs_block **indirect1[CYGNUM_RAMFS_BLOCKS_INDIRECT1];
459 #if CYGNUM_RAMFS_BLOCKS_INDIRECT2 > 0
460 // Two level indirection
461 ramfs_block ***indirect2[CYGNUM_RAMFS_BLOCKS_INDIRECT2];
468 //==========================================================================
470 // Fixed sized entry containing a fragment of the name of a file/directory.
474 ramfs_node *node; // pointer to node
475 unsigned int inuse:1, // entry in use?
476 first:1, // first directory entry fragment?
477 last:1, // last directory entry fragment?
478 namelen:8, // bytes in whole name
479 fraglen:8; // bytes in name fragment
480 off_t next; // offset of next dirent
482 // Name fragment, fills rest of entry.
483 char name[CYGNUM_RAMFS_DIRENT_SIZE-
484 sizeof(ramfs_node *)-
489 //==========================================================================
490 // Directory search data
491 // Parameters for a directory search. The fields of this structure are
492 // updated as we follow a pathname through the directory tree.
494 struct ramfs_dirsearch
496 ramfs_node *dir; // directory to search
497 const char *path; // path to follow
498 ramfs_node *node; // Node found
499 const char *name; // last name fragment used
500 int namelen; // name fragment length
501 cyg_bool last; // last name in path?
504 typedef struct ramfs_dirsearch ramfs_dirsearch;
506 //==========================================================================
509 static int del_direntry( ramfs_node *dir, const char *name, int namelen );
512 //==========================================================================
514 // This is used for block allocation when malloc is not being used.
516 #ifdef CYGPKG_FS_RAM_BLOCKS_ARRAY
518 # ifdef CYGPKG_FS_RAM_BLOCKS_ARRAY_EXTERN
520 // Array is defined externally with a user-supplied name
522 __externC ramfs_block CYGPKG_FS_RAM_BLOCKS_ARRAY_NAME[CYGNUM_FS_RAM_BLOCKS_ARRAY_SIZE];
524 // Translate into a usable common name
525 #define ramfs_block_array CYGPKG_FS_RAM_BLOCKS_ARRAY_NAME
529 // Array is defined here
531 static ramfs_block cyg_ramfs_block_array[CYGNUM_FS_RAM_BLOCKS_ARRAY_SIZE];
533 #define ramfs_block_array cyg_ramfs_block_array
537 // Pointer to list of free blocks
538 static ramfs_block *block_free_list = NULL;
542 //==========================================================================
545 #ifndef CYGPKG_FS_RAM_SIMPLE
547 // -------------------------------------------------------------------------
549 // Initialize the block allocator by chaining them all together on
552 #ifdef CYGPKG_FS_RAM_BLOCKS_ARRAY
554 static void block_init(void)
556 static cyg_bool initialized = false;
561 for( i = 0; i < CYGNUM_FS_RAM_BLOCKS_ARRAY_SIZE; i++ )
563 ramfs_block *b = &ramfs_block_array[i];
564 *(ramfs_block **)b = block_free_list;
573 // -------------------------------------------------------------------------
575 // Allocate a block for data storage.
576 // If we have a block array, just pick the first off the free list.
577 // If we are mallocing, call malloc() to get it.
579 static ramfs_block *block_alloc(void)
583 #ifdef CYGPKG_FS_RAM_BLOCKS_ARRAY
585 block_init(); // Check blocks are initialized
587 // pick first block off free list.
592 block_free_list = *(ramfs_block **)b;
596 b = malloc(CYGNUM_RAMFS_BLOCK_SIZE);
600 // Clear the block to zero if it was allocated
602 memset( b, 0, CYGNUM_RAMFS_BLOCK_SIZE );
608 // -------------------------------------------------------------------------
610 // Free a block. Depending on the configuration send it back to the
611 // heap or put it back on free list.
613 static void block_free( ramfs_block *b )
615 #ifdef CYGPKG_FS_RAM_BLOCKS_ARRAY
617 // Put the block back on the free list
619 *(ramfs_block **)b = block_free_list;
624 // Call free() to return it to the memory pool
633 //==========================================================================
634 // Node buffer management
635 // There are two versions of this, one for the _SIMPLE variant and one for
636 // the _BLOCKS variant. In both cases the interface to this code is via the
637 // findbuffer_node() and freebuffer_node() functions.
639 #ifdef CYGPKG_FS_RAM_SIMPLE
641 //==========================================================================
642 // SIMPLE buffer management.
643 // Each node has a data buffer pointer and a size. This buffer is
644 // realloc()ed as needed.
646 // -------------------------------------------------------------------------
648 // return a pointer to the data at the indicated file position, extending
649 // the buffer if required.
651 static int findbuffer_node( ramfs_node *node, // node pointer
652 off_t pos, // data position to get
653 cyg_uint8 **buffer, // returned buffer pointer
654 size_t *size, // returned buffer size
655 cyg_bool alloc) // extend allocation?
657 if( alloc && (pos == node->datasize || node->datasize == 0) )
659 // If we are allowed to alloc new data, and we are at the end of the
660 // current data allocation, or there is no data present, allocate or
661 // extend the data buffer.
665 if( node->data == NULL )
666 newdata = malloc( CYGNUM_RAMFS_REALLOC_INCREMENT );
668 newdata = realloc( node->data, pos+CYGNUM_RAMFS_REALLOC_INCREMENT );
670 if( newdata == NULL ) return ENOSPC;
671 else memset( newdata+pos, 0, CYGNUM_RAMFS_REALLOC_INCREMENT );
673 node->data = newdata;
674 node->datasize = pos+CYGNUM_RAMFS_REALLOC_INCREMENT;
676 else if( pos > node->datasize )
678 // Indicate end of data.
683 *buffer = node->data+pos;
684 *size = node->datasize-pos;
689 // -------------------------------------------------------------------------
691 // Empty out the data storage from the node.
693 static int freebuffer_node( ramfs_node *node )
695 if( node->data != NULL )
706 //==========================================================================
710 //==========================================================================
711 // _BLOCKS storage management.
712 // Data storage in the node is by means of a set of arrays of pointers to
713 // blocks. The first array points directly to the data blocks. Subsequent
714 // arrays point to single and double indirect blocks respectively.
716 // -------------------------------------------------------------------------
717 // findbuffer_direct()
718 // Indexes into an array of block pointers and extracts a pointer to the
719 // data at offset _pos_, allocating new blocks if required.
721 static int findbuffer_direct( off_t pos,
722 ramfs_block **blocks,
728 int bi = pos / CYGNUM_RAMFS_BLOCK_SIZE;
729 int bpos = pos % CYGNUM_RAMFS_BLOCK_SIZE;
742 // There is no block there. If _alloc_ is true we can fill the
743 // slot in with a new block. If it is false, we indicate end of
744 // data with a zero size result.
755 *buffer = &((*b)[bpos]);
756 *size = CYGNUM_RAMFS_BLOCK_SIZE - bpos;
761 // -------------------------------------------------------------------------
762 // findbuffer_indirect1()
763 // Indexes into an array of pointers to blocks containing pointers to
764 // blocks and extracts a pointer to the data at offset _pos_,
765 // allocating new blocks if required.
767 #if CYGNUM_RAMFS_BLOCKS_INDIRECT1 > 0
769 static int findbuffer_indirect1( off_t pos,
770 ramfs_block ***blocks,
777 int bi = pos / RAMFS_INDIRECT1_BLOCK_EXTENT;
778 int bpos = pos % RAMFS_INDIRECT1_BLOCK_EXTENT;
783 // Use findbuffer_direct() to index and allocate
784 // the first level indirect block.
786 err = findbuffer_direct( bi*CYGNUM_RAMFS_BLOCK_SIZE,
787 (ramfs_block **)blocks,
802 // Use findbuffer_direct() on the first level indirect
803 // block to allocate and return the data pointer.
805 return findbuffer_direct( bpos,
807 RAMFS_INDIRECT_PER_BLOCK,
815 // -------------------------------------------------------------------------
816 // findbuffer_indirect1()
817 // Indexes into an array of pointers to blocks containing pointers to
818 // blocks containing pointers to blocks (!) and extracts a pointer to
819 // the data at offset _pos_, allocating new blocks if required.
821 #if CYGNUM_RAMFS_BLOCKS_INDIRECT2 > 0
823 static int findbuffer_indirect2( off_t pos,
824 ramfs_block ****blocks,
830 int bi = pos / RAMFS_INDIRECT2_BLOCK_EXTENT;
831 int bpos = pos % RAMFS_INDIRECT2_BLOCK_EXTENT;
836 // Use findbuffer_direct() to index and allocate
837 // the first level indirect block.
839 err = findbuffer_direct( bi*CYGNUM_RAMFS_BLOCK_SIZE,
840 (ramfs_block **)blocks,
855 // Use findbuffer_indirect1() on the first level indirect block to
856 // index and allocate the next level indirect block and the data
859 return findbuffer_indirect1( bpos,
861 RAMFS_INDIRECT_PER_BLOCK,
869 // -------------------------------------------------------------------------
871 // Depending on the offset and configuration, call the appropriate
872 // function to get the buffer pointer.
874 static int findbuffer_node( ramfs_node *node,
880 #if CYGNUM_RAMFS_BLOCKS_DIRECT > 0
881 if( pos < RAMFS_DIRECT_MAX )
882 return findbuffer_direct( pos,
884 CYGNUM_RAMFS_BLOCKS_DIRECT,
889 #if CYGNUM_RAMFS_BLOCKS_INDIRECT1 > 0
890 if( pos < RAMFS_INDIRECT1_MAX )
891 return findbuffer_indirect1( pos - RAMFS_DIRECT_MAX,
893 CYGNUM_RAMFS_BLOCKS_INDIRECT1,
898 #if CYGNUM_RAMFS_BLOCKS_INDIRECT2 > 0
899 if( pos < RAMFS_INDIRECT2_MAX )
900 return findbuffer_indirect2( pos - RAMFS_INDIRECT1_MAX,
902 CYGNUM_RAMFS_BLOCKS_INDIRECT2,
911 // -------------------------------------------------------------------------
913 // Free a list of data blocks.
915 static void freeblock_list( ramfs_block *blocks[],int nblocks )
918 for( i = 0; i < nblocks ; i++ )
920 if( blocks[i] != NULL )
922 block_free( blocks[i] );
928 // -------------------------------------------------------------------------
930 // Free all the data blocks in the node and clear the pointers.
932 static int freebuffer_node( ramfs_node *node )
934 #if CYGNUM_RAMFS_BLOCKS_DIRECT > 0
935 freeblock_list( node->direct, CYGNUM_RAMFS_BLOCKS_DIRECT );
938 #if CYGNUM_RAMFS_BLOCKS_INDIRECT1 > 0
941 for( i = 0; i < CYGNUM_RAMFS_BLOCKS_INDIRECT1 ; i++ )
943 if( node->indirect1[i] != NULL )
945 freeblock_list( (ramfs_block **)node->indirect1[i], RAMFS_INDIRECT_PER_BLOCK );
946 block_free( (ramfs_block *)node->indirect1[i] );
947 node->indirect1[i] = NULL;
953 #if CYGNUM_RAMFS_BLOCKS_INDIRECT2 > 0
956 for( i = 0; i < CYGNUM_RAMFS_BLOCKS_INDIRECT2 ; i++ )
958 if( node->indirect2[i] != NULL )
960 ramfs_block ***b = node->indirect2[i];
962 for( j = 0; j < RAMFS_INDIRECT_PER_BLOCK ; j++ )
966 freeblock_list( (ramfs_block **)b[j], RAMFS_INDIRECT_PER_BLOCK );
967 block_free( (ramfs_block *)b[j] );
971 block_free( (ramfs_block *)node->indirect2[i] );
972 node->indirect2[i] = NULL;
981 //==========================================================================
985 //==========================================================================
988 // -------------------------------------------------------------------------
990 // Allocate a node and initialize it.
991 // For the _SIMPLE allocation option, we just malloc it. For the
992 // _BLOCKS option we allocate a block and use that. In theory we could
993 // pack several nodes into a single block, but we don't at present due
994 // to sheer lazyness.
996 static ramfs_node *alloc_node( mode_t mode )
998 #ifdef CYGPKG_FS_RAM_SIMPLE
999 ramfs_node *node = malloc( sizeof( ramfs_node ) );
1005 ramfs_block *b = block_alloc();
1011 node = (ramfs_node *)b;
1015 memset( node, 0, sizeof(ramfs_node) );
1023 node->ctime = cyg_timestamp();
1025 #ifdef CYGPKG_FS_RAM_SIMPLE
1030 // The node is already all zero
1036 // -------------------------------------------------------------------------
1038 // Release a node either back to the free pool or back into the block
1041 static void free_node( ramfs_node *node )
1043 #ifdef CYGPKG_FS_RAM_SIMPLE
1049 block_free( (ramfs_block *)node );
1056 //==========================================================================
1057 // Ref count and nlink management
1059 // -------------------------------------------------------------------------
1061 // Decrment the reference count on a node. If this makes the ref count
1062 // zero, and the number of links is either zero for a file or one for
1063 // a node, then this node is detached from the directory tree and can
1066 static int dec_refcnt( ramfs_node *node )
1071 if( node->refcnt == 0 &&
1072 ((S_ISREG(node->mode) && node->nlink == 0 ) ||
1073 (S_ISDIR(node->mode) && node->nlink == 1) )
1076 // This node it now totally detached from the directory tree,
1079 if( S_ISDIR(node->mode) )
1081 del_direntry( node, ".", 1 );
1082 del_direntry( node, "..", 2 );
1085 err = freebuffer_node( node );
1094 // -------------------------------------------------------------------------
1096 // Decrement a node's link count. Since this has to do all the same
1097 // work as dec_refcnt() we implement this using that function by
1098 // essentially transferring the count to refcnt and then decrement
1101 static int dec_nlink( ramfs_node *node )
1107 return dec_refcnt( node );
1110 //==========================================================================
1111 // Directory operations
1113 // -------------------------------------------------------------------------
1115 // Add an entry to a directory. This is added as a chain of entry
1116 // fragments until the name is exhausted.
1118 static int add_direntry( ramfs_node *dir, // dir to add to
1119 const char *name, // name to add
1120 int namelen, // length of name
1121 ramfs_node *node // node to reference
1125 ramfs_dirent *d = NULL, *dp = NULL;
1126 cyg_bool isfirst = true;
1128 // Loop inserting fragments of the name into the directory until we
1129 // have found a home for them all.
1131 while( namelen > 0 )
1133 int fraglen = namelen;
1135 if( fraglen > sizeof(d->name) )
1136 fraglen = sizeof(d->name);
1138 // Find a free fragment
1143 int err = findbuffer_node( dir, pos, &buf, &size, true );
1144 if( err != ENOERR ) return err;
1146 d = (ramfs_dirent *)buf;
1148 if( size < sizeof(ramfs_dirent) || d->inuse )
1150 pos += sizeof(ramfs_dirent);
1157 // d now points to a free dirent structure
1162 d->namelen = namelen;
1163 d->fraglen = fraglen;
1164 if( dp ) dp->next = pos;
1166 memcpy( d->name, name, fraglen );
1170 pos += sizeof(ramfs_dirent);
1177 d->last = 1; // Mark last fragment
1179 // Update directory times
1181 dir->ctime = cyg_timestamp();
1183 // Extend dir size if necessary
1184 if( pos > dir->size )
1187 // Count the new link
1193 // -------------------------------------------------------------------------
1195 // Find a directory entry for the name and return a pointer to the first
1198 static ramfs_dirent *find_direntry( ramfs_node *dir, const char *name, int namelen )
1200 ramfs_dirent *first = NULL;
1204 // Loop over all the entries until a match is found or we run out
1206 while( pos < dir->size )
1208 const char *frag = name;
1213 // look for a first name fragment
1216 err = findbuffer_node( dir, pos, &buf, &size, false );
1217 if( err != ENOERR || size == 0)
1220 d = (ramfs_dirent *)buf;
1222 if( size < sizeof(ramfs_dirent) || !d->inuse || !d->first )
1224 pos += sizeof(ramfs_dirent);
1231 // Here we have got a first fragment of a name, check it
1232 // against the name we are looking for. First check that they
1233 // are the same length.
1235 if( d->namelen == namelen )
1237 // We have a potential candidate here...
1239 first = d; // Save it for later
1241 // Now check that all the name fragments match
1244 int fraglen = namelen-(frag-name);
1246 if( fraglen > d->fraglen )
1247 fraglen = d->fraglen;
1249 // compare strings, if different, look for another
1250 if( memcmp( frag, d->name, fraglen ) != 0 )
1255 // If we are at the last fragment, then the whole name string
1256 // has matched and we have a successful search.
1261 // Otherwise move on to next entry in chain
1262 err = findbuffer_node( dir, d->next, &buf, &size, false );
1266 d = (ramfs_dirent *)buf;
1271 pos += sizeof(ramfs_dirent);
1277 // -------------------------------------------------------------------------
1279 // Delete a named directory entry. Find it and then follow the chain
1280 // deleting the fragments as we go.
1282 static int del_direntry( ramfs_node *dir, const char *name, int namelen )
1284 ramfs_dirent *d = find_direntry( dir, name, namelen );
1296 if( d->last ) break;
1298 err = findbuffer_node( dir, d->next, &buf, &size, false );
1302 d = (ramfs_dirent *)buf;
1305 dec_nlink( d->node );
1310 //==========================================================================
1313 // -------------------------------------------------------------------------
1315 // Initialize a dirsearch object to start a search
1317 static void init_dirsearch( ramfs_dirsearch *ds,
1329 // -------------------------------------------------------------------------
1331 // Search a single directory for the next name in a path and update the
1332 // dirsearch object appropriately.
1334 static int find_entry( ramfs_dirsearch *ds )
1336 ramfs_node *dir = ds->dir;
1337 const char *name = ds->path;
1338 const char *n = name;
1342 // check that we really have a directory
1343 if( !S_ISDIR(dir->mode) )
1346 // Isolate the next element of the path name.
1347 while( *n != '\0' && *n != '/' )
1350 // Check if this is the last path element.
1351 while( *n == '/') n++;
1355 // update name in dirsearch object
1357 ds->namelen = namelen;
1359 // Here we have the name and its length set up.
1360 // Search the directory for a matching entry
1362 d = find_direntry( dir, name, namelen );
1367 // pass back the node we have found
1374 // -------------------------------------------------------------------------
1376 // Main interface to directory search code. This is used in all file
1377 // level operations to locate the object named by the pathname.
1379 static int ramfs_find( ramfs_dirsearch *d )
1383 // Short circuit empty paths
1384 if( *(d->path) == '\0' )
1387 // iterate down directory tree until we find the object
1391 err = find_entry( d );
1399 // Update dirsearch object to search next directory.
1401 d->path += d->namelen;
1402 while( *(d->path) == '/' ) d->path++; // skip dirname separators
1406 //==========================================================================
1408 // This function provides support for pathconf() and fpathconf().
1410 static int ramfs_pathconf( ramfs_node *node, struct cyg_pathconf_info *info )
1414 switch( info->name )
1417 info->value = LINK_MAX;
1421 info->value = -1; // not supported
1426 info->value = -1; // not supported
1431 info->value = NAME_MAX;
1435 info->value = PATH_MAX;
1439 info->value = -1; // not supported
1445 info->value = -1; // not supported
1449 case _PC_CHOWN_RESTRICTED:
1450 info->value = -1; // not supported
1467 info->value = -1; // not supported
1479 //==========================================================================
1480 // Filesystem operations
1482 // -------------------------------------------------------------------------
1484 // Process a mount request. This mainly creates a root for the
1487 static int ramfs_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte )
1492 // Allocate a node to be the root of this filesystem and initialize it.
1494 root = alloc_node(__stat_mode_DIR);
1499 // Add . and .. entries back to self.
1501 err = add_direntry( root, ".", 1, root );
1503 err = add_direntry( root, "..", 2, root );
1511 mte->root = (cyg_dir)root;
1516 // -------------------------------------------------------------------------
1518 // Unmount the filesystem. This will currently only succeed if the
1519 // filesystem is empty.
1521 static int ramfs_umount ( cyg_mtab_entry *mte )
1523 ramfs_node *root = (ramfs_node *)mte->root;
1525 // Check for open/inuse root
1526 if( root->refcnt != 0 )
1529 // Check that root directory is clear of extra links.
1530 if( root->nlink != 2 )
1533 // Just return it to free pool
1536 // Clear root pointer
1537 mte->root = CYG_DIR_NULL;
1539 // That's all folks.
1544 // -------------------------------------------------------------------------
1546 // Open a file for reading or writing.
1548 static int ramfs_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1549 int mode, cyg_file *file )
1553 ramfs_node *node = NULL;
1556 init_dirsearch( &ds, (ramfs_node *)dir, name );
1558 err = ramfs_find( &ds );
1562 if( ds.last && (mode & O_CREAT) )
1564 // No node there, if the O_CREAT bit is set then we must
1565 // create a new one. The dir and name fields of the dirsearch
1566 // object will have been updated so we know where to put it.
1568 node = alloc_node( __stat_mode_REG );
1573 err = add_direntry( ds.dir, ds.name, ds.namelen, node );
1584 else if( err == ENOERR )
1586 // The node exists. If the O_CREAT and O_EXCL bits are set, we
1587 // must fail the open.
1589 if( (mode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) )
1591 else node = ds.node;
1594 if( err == ENOERR && (mode & O_TRUNC ) )
1596 // If the O_TRUNC bit is set we must clean out the file data.
1598 err = freebuffer_node( node );
1601 // Update file times
1603 node->mtime = cyg_timestamp();
1606 if( err != ENOERR ) return err;
1608 // Check that we actually have a file here
1609 if( S_ISDIR(node->mode) ) return EISDIR;
1611 node->refcnt++; // Count successful open
1613 // Initialize the file object
1615 file->f_flag |= mode & CYG_FILE_MODE_MASK;
1616 file->f_type = CYG_FILE_TYPE_FILE;
1617 file->f_ops = &ramfs_fileops;
1618 file->f_offset = (mode&O_APPEND) ? node->size : 0;
1619 file->f_data = (CYG_ADDRWORD)node;
1625 // -------------------------------------------------------------------------
1627 // Remove a file link from its directory.
1629 static int ramfs_unlink ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
1634 init_dirsearch( &ds, (ramfs_node *)dir, name );
1636 err = ramfs_find( &ds );
1638 if( err != ENOERR ) return err;
1640 // Cannot unlink directories, use rmdir() instead
1641 if( S_ISDIR(ds.node->mode) )
1644 // Delete it from its directory
1645 err = del_direntry( ds.dir, ds.name, ds.namelen );
1650 // -------------------------------------------------------------------------
1652 // Create a new directory.
1654 static int ramfs_mkdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
1657 ramfs_node *node = NULL;
1660 init_dirsearch( &ds, (ramfs_node *)dir, name );
1662 err = ramfs_find( &ds );
1668 // The entry does not exist, and it is the last element in
1669 // the pathname, so we can create it here.
1670 int doterr, dotdoterr, direrr;
1672 node = alloc_node( __stat_mode_DIR );
1677 // Add "." and ".." entries.
1678 doterr = add_direntry( node, ".", 1, node );
1679 dotdoterr = add_direntry( node, "..", 2, ds.dir );
1681 // And add to parent directory.
1682 direrr = add_direntry( ds.dir, ds.name, ds.namelen, node );
1684 // check for any errors in that...
1685 if( doterr+dotdoterr+direrr != ENOERR )
1687 // For each of the add_direntry() calls that succeeded,
1688 // we must now undo it.
1690 if( doterr == ENOERR )
1691 del_direntry( node, ".", 1 );
1694 if( dotdoterr == ENOERR )
1695 del_direntry( node, "..", 2 );
1696 else err = dotdoterr;
1698 if( direrr == ENOERR )
1699 del_direntry( ds.dir, ds.name, ds.namelen );
1702 // Free the data and the node itself.
1703 freebuffer_node( node );
1708 // If this was not the last element, then and intermediate
1709 // directory does not exist.
1713 // If there we no error, something already exists with that
1714 // name, so we cannot create another one.
1723 // -------------------------------------------------------------------------
1725 // Remove a directory.
1727 static int ramfs_rmdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
1732 init_dirsearch( &ds, (ramfs_node *)dir, name );
1734 err = ramfs_find( &ds );
1736 if( err != ENOERR ) return err;
1738 // Check that this is actually a directory.
1739 if( !S_ISDIR(ds.node->mode) )
1742 // Delete the entry. This will adjust the link values
1743 // accordingly and if the directory is now unreferenced,
1744 // will cause it to be deleted.
1746 err = del_direntry( ds.dir, ds.name, ds.namelen );
1751 // -------------------------------------------------------------------------
1753 // Rename a file/dir.
1755 static int ramfs_rename ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
1756 cyg_dir dir2, const char *name2 )
1758 ramfs_dirsearch ds1, ds2;
1761 init_dirsearch( &ds1, (ramfs_node *)dir1, name1 );
1763 err = ramfs_find( &ds1 );
1765 if( err != ENOERR ) return err;
1767 init_dirsearch( &ds2, (ramfs_node *)dir2, name2 );
1769 err = ramfs_find( &ds2 );
1771 // Allow through renames to non-existent objects.
1772 if( ds2.last && err == ENOENT )
1773 ds2.node = NULL, err = ENOERR;
1775 if( err != ENOERR ) return err;
1777 // Null rename, just return
1778 if( ds1.node == ds2.node )
1781 // First deal with any entry that is at the destination
1784 // Check that we are renaming like-for-like
1786 if( !S_ISDIR(ds1.node->mode) && S_ISDIR(ds2.node->mode) )
1789 if( S_ISDIR(ds1.node->mode) && !S_ISDIR(ds2.node->mode) )
1792 // Now delete the destination directory entry
1794 err = del_direntry( ds2.dir, ds2.name, ds2.namelen );
1796 if( err != ENOERR ) return err;
1800 // Now we know that there is no clashing node at the destination,
1801 // make a new direntry at the destination and delete the old entry
1804 err = add_direntry( ds2.dir, ds2.name, ds2.namelen, ds1.node );
1807 err = del_direntry( ds1.dir, ds1.name, ds1.namelen );
1809 // Update directory times
1814 ds2.dir->mtime = cyg_timestamp();
1819 // -------------------------------------------------------------------------
1821 // Make a new directory entry for a file.
1823 static int ramfs_link ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
1824 cyg_dir dir2, const char *name2, int type )
1826 ramfs_dirsearch ds1, ds2;
1829 // Only do hard links for now in this filesystem
1830 if( type != CYG_FSLINK_HARD )
1833 init_dirsearch( &ds1, (ramfs_node *)dir1, name1 );
1835 err = ramfs_find( &ds1 );
1837 if( err != ENOERR ) return err;
1839 init_dirsearch( &ds2, (ramfs_node *)dir2, name2 );
1841 err = ramfs_find( &ds2 );
1843 // Don't allow links to existing objects
1844 if( err == ENOERR ) return EEXIST;
1846 // Allow through links to non-existing terminal objects
1847 if( ds2.last && err == ENOENT )
1848 ds2.node = NULL, err = ENOERR;
1850 if( err != ENOERR ) return err;
1852 // Now we know that there is no existing node at the destination,
1853 // make a new direntry at the destination.
1855 err = add_direntry( ds2.dir, ds2.name, ds2.namelen, ds1.node );
1860 ds2.dir->mtime = cyg_timestamp();
1865 // -------------------------------------------------------------------------
1867 // Open a directory for reading.
1869 static int ramfs_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1875 init_dirsearch( &ds, (ramfs_node *)dir, name );
1877 err = ramfs_find( &ds );
1879 if( err != ENOERR ) return err;
1881 // check it is really a directory.
1882 if( !S_ISDIR(ds.node->mode) ) return ENOTDIR;
1884 ds.node->refcnt++; // Count successful open
1886 // Initialize the file object, setting the f_ops field to a
1887 // special set of file ops.
1889 file->f_type = CYG_FILE_TYPE_FILE;
1890 file->f_ops = &ramfs_dirops;
1892 file->f_data = (CYG_ADDRWORD)ds.node;
1899 // -------------------------------------------------------------------------
1901 // Change directory support.
1903 static int ramfs_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1906 if( dir_out != NULL )
1908 // This is a request to get a new directory pointer in
1914 init_dirsearch( &ds, (ramfs_node *)dir, name );
1916 err = ramfs_find( &ds );
1918 if( err != ENOERR ) return err;
1920 // check it is a directory
1921 if( !S_ISDIR(ds.node->mode) )
1924 // Increment ref count to keep this directory in existent
1925 // while it is the current cdir.
1929 *dir_out = (cyg_dir)ds.node;
1933 // If no output dir is required, this means that the mte and
1934 // dir arguments are the current cdir setting and we should
1935 // forget this fact.
1937 ramfs_node *node = (ramfs_node *)dir;
1939 // Just decrement directory reference count.
1946 // -------------------------------------------------------------------------
1948 // Get struct stat info for named object.
1950 static int ramfs_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1956 init_dirsearch( &ds, (ramfs_node *)dir, name );
1958 err = ramfs_find( &ds );
1960 if( err != ENOERR ) return err;
1962 // Fill in the status
1963 buf->st_mode = ds.node->mode;
1964 buf->st_ino = (ino_t)ds.node;
1966 buf->st_nlink = ds.node->nlink;
1969 buf->st_size = ds.node->size;
1970 buf->st_atime = ds.node->atime;
1971 buf->st_mtime = ds.node->mtime;
1972 buf->st_ctime = ds.node->ctime;
1977 // -------------------------------------------------------------------------
1979 // Getinfo. Currently only support pathconf().
1981 static int ramfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1982 int key, void *buf, int len )
1987 init_dirsearch( &ds, (ramfs_node *)dir, name );
1989 err = ramfs_find( &ds );
1991 if( err != ENOERR ) return err;
1996 err = ramfs_pathconf( ds.node, (struct cyg_pathconf_info *)buf );
2005 // -------------------------------------------------------------------------
2007 // Setinfo. Nothing to support here at present.
2009 static int ramfs_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2010 int key, void *buf, int len )
2012 // No setinfo keys supported at present
2018 //==========================================================================
2021 // -------------------------------------------------------------------------
2023 // Read data from the file.
2025 static int ramfs_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2027 ramfs_node *node = (ramfs_node *)fp->f_data;
2029 off_t pos = fp->f_offset;
2030 ssize_t resid = uio->uio_resid;
2032 // Loop over the io vectors until there are none left
2033 for( i = 0; i < uio->uio_iovcnt; i++ )
2035 cyg_iovec *iov = &uio->uio_iov[i];
2036 char *buf = (char *)iov->iov_base;
2037 off_t len = iov->iov_len;
2039 // Loop over each vector filling it with data from the file.
2040 while( len > 0 && pos < node->size )
2047 // Get a pointer to the data at offset _pos_.
2048 err = findbuffer_node( node, pos, &fbuf, &bsize, false );
2053 // adjust size to end of file if necessary
2054 if( l > node->size-pos )
2057 // adjust size to the amount of contiguous data we can see
2063 memcpy( buf, fbuf, l );
2065 // Update working vars
2073 // We successfully read some data, update the node's access time
2074 // and update the file offset and transfer residue.
2076 node->atime = cyg_timestamp();
2078 uio->uio_resid = resid;
2084 // -------------------------------------------------------------------------
2086 // Write data to file.
2088 static int ramfs_fo_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2090 ramfs_node *node = (ramfs_node *)fp->f_data;
2091 off_t pos = fp->f_offset;
2092 ssize_t resid = uio->uio_resid;
2096 // If the APPEND mode bit was supplied, force all writes to
2097 // the end of the file.
2098 if( fp->f_flag & CYG_FAPPEND )
2099 pos = fp->f_offset = node->size;
2101 // Check that pos is within current file size, or at the very end.
2102 if( pos < 0 || pos > node->size )
2105 // Now loop over the iovecs until they are all done, or
2107 for( i = 0; i < uio->uio_iovcnt; i++ )
2109 cyg_iovec *iov = &uio->uio_iov[i];
2110 char *buf = (char *)iov->iov_base;
2111 off_t len = iov->iov_len;
2113 // loop over the vector writing it to the file until it has
2121 err = findbuffer_node( node, pos, &fbuf, &bsize, true );
2123 // Stop writing if there is no more space in the file and
2124 // indicate end of data.
2131 // adjust size to this block
2136 memcpy( fbuf, buf, l );
2138 // Update working vars
2146 // We wrote some data successfully, update the modified and access
2147 // times of the node, increase its size appropriately, and update
2148 // the file offset and transfer residue.
2150 node->ctime = cyg_timestamp();
2151 if( pos > node->size )
2154 uio->uio_resid = resid;
2160 // -------------------------------------------------------------------------
2162 // Seek to a new file position.
2164 static int ramfs_fo_lseek (struct CYG_FILE_TAG *fp, off_t *apos, int whence )
2166 ramfs_node *node = (ramfs_node *)fp->f_data;
2172 // Pos is already where we want to be.
2176 // Add pos to current offset.
2177 pos += fp->f_offset;
2181 // Add pos to file size.
2189 // Check that pos is still within current file size, or at the
2191 if( pos < 0 || pos > node->size )
2194 // All OK, set fp offset and return new position.
2195 *apos = fp->f_offset = pos;
2200 // -------------------------------------------------------------------------
2202 // Handle ioctls. Currently none are defined.
2204 static int ramfs_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
2207 // No Ioctls currenly defined.
2212 // -------------------------------------------------------------------------
2213 // ramfs_fo_fsync().
2214 // Force the file out to data storage.
2216 static int ramfs_fo_fsync (struct CYG_FILE_TAG *fp, int mode )
2218 // Data is always permanently where it belongs, nothing to do
2224 // -------------------------------------------------------------------------
2226 // Close a file. We just decrement the refcnt and let it go away if
2227 // that is all that is keeping it here.
2229 static int ramfs_fo_close (struct CYG_FILE_TAG *fp)
2231 ramfs_node *node = (ramfs_node *)fp->f_data;
2235 fp->f_data = 0; // zero data pointer
2240 // -------------------------------------------------------------------------
2244 static int ramfs_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf )
2246 ramfs_node *node = (ramfs_node *)fp->f_data;
2248 // Fill in the status
2249 buf->st_mode = node->mode;
2250 buf->st_ino = (ino_t)node;
2252 buf->st_nlink = node->nlink;
2255 buf->st_size = node->size;
2256 buf->st_atime = node->atime;
2257 buf->st_mtime = node->mtime;
2258 buf->st_ctime = node->ctime;
2263 // -------------------------------------------------------------------------
2264 // ramfs_fo_getinfo()
2265 // Get info. Currently only supports fpathconf().
2267 static int ramfs_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
2269 ramfs_node *node = (ramfs_node *)fp->f_data;
2275 err = ramfs_pathconf( node, (struct cyg_pathconf_info *)buf );
2284 // -------------------------------------------------------------------------
2285 // ramfs_fo_setinfo()
2286 // Set info. Nothing supported here.
2288 static int ramfs_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
2290 // No setinfo key supported at present
2296 //==========================================================================
2297 // Directory operations
2299 // -------------------------------------------------------------------------
2300 // ramfs_fo_dirread()
2301 // Read a single directory entry from a file.
2303 static int ramfs_fo_dirread (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2305 ramfs_node *dir = (ramfs_node *)fp->f_data;
2306 off_t pos = fp->f_offset;
2308 struct dirent *ent = (struct dirent *)uio->uio_iov[0].iov_base;
2309 char *nbuf = ent->d_name;
2310 int nlen = sizeof(ent->d_name)-1;
2311 off_t len = uio->uio_iov[0].iov_len;
2312 ramfs_dirent *d = NULL;
2316 if( len < sizeof(struct dirent) )
2319 // look for a first name fragment
2321 while( pos < dir->size )
2323 err = findbuffer_node( dir, pos, &buf, &size, false );
2324 if( err != ENOERR || size == 0)
2327 d = (ramfs_dirent *)buf;
2329 if( size < sizeof(ramfs_dirent) || !d->inuse || !d->first )
2331 pos += sizeof(ramfs_dirent);
2338 // Check we have not exceeded the size of the directory.
2339 if( pos == dir->size )
2342 // Here we have the first fragment of a directory entry.
2346 int fraglen = d->fraglen;
2348 // adjust to allow for remaining space in dirent struct
2349 if( fraglen > nlen )
2352 memcpy( nbuf, d->name, fraglen);
2356 // if we hit the last entry, we have a successful transfer
2357 if( d->last || nlen == 0)
2360 // Otherwise move on to next entry in chain
2361 err = findbuffer_node( dir, d->next, &buf, &size, false );
2365 d = (ramfs_dirent *)buf;
2368 // A successful read. Terminate the entry name with a NUL, set the
2369 // residue and set the file offset to restart at the next
2373 uio->uio_resid -= sizeof(struct dirent);
2374 fp->f_offset = pos+sizeof(ramfs_dirent);
2379 // -------------------------------------------------------------------------
2380 // ramfs_fo_dirlseek()
2381 // Seek directory to start.
2383 static int ramfs_fo_dirlseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence )
2385 // Only allow SEEK_SET to zero
2387 if( whence != SEEK_SET || *pos != 0)
2390 *pos = fp->f_offset = 0;
2395 // -------------------------------------------------------------------------