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 + node->datasize, 0,
672 pos + CYGNUM_RAMFS_REALLOC_INCREMENT - node->datasize );
674 node->data = newdata;
675 node->datasize = pos+CYGNUM_RAMFS_REALLOC_INCREMENT;
677 else if( pos > node->datasize )
679 // Indicate end of data.
684 *buffer = node->data+pos;
685 *size = node->datasize-pos;
690 // -------------------------------------------------------------------------
692 // Empty out the data storage from the node.
694 static int freebuffer_node( ramfs_node *node )
696 if( node->data != NULL )
707 //==========================================================================
711 //==========================================================================
712 // _BLOCKS storage management.
713 // Data storage in the node is by means of a set of arrays of pointers to
714 // blocks. The first array points directly to the data blocks. Subsequent
715 // arrays point to single and double indirect blocks respectively.
717 // -------------------------------------------------------------------------
718 // findbuffer_direct()
719 // Indexes into an array of block pointers and extracts a pointer to the
720 // data at offset _pos_, allocating new blocks if required.
722 static int findbuffer_direct( off_t pos,
723 ramfs_block **blocks,
729 int bi = pos / CYGNUM_RAMFS_BLOCK_SIZE;
730 int bpos = pos % CYGNUM_RAMFS_BLOCK_SIZE;
734 *size = CYGNUM_RAMFS_BLOCK_SIZE - bpos;
743 // There is no block there. If _alloc_ is true we can fill the
744 // slot in with a new block. If it is false, we indicate there
745 // is no block and size indicates where the block would end if
757 *buffer = &((*b)[bpos]);
762 // -------------------------------------------------------------------------
763 // findbuffer_indirect1()
764 // Indexes into an array of pointers to blocks containing pointers to
765 // blocks and extracts a pointer to the data at offset _pos_,
766 // allocating new blocks if required.
768 #if CYGNUM_RAMFS_BLOCKS_INDIRECT1 > 0
770 static int findbuffer_indirect1( off_t pos,
771 ramfs_block ***blocks,
778 int bi = pos / RAMFS_INDIRECT1_BLOCK_EXTENT;
779 int bpos = pos % RAMFS_INDIRECT1_BLOCK_EXTENT;
784 // Use findbuffer_direct() to index and allocate
785 // the first level indirect block.
787 err = findbuffer_direct( bi*CYGNUM_RAMFS_BLOCK_SIZE,
788 (ramfs_block **)blocks,
803 // Use findbuffer_direct() on the first level indirect
804 // block to allocate and return the data pointer.
806 return findbuffer_direct( bpos,
808 RAMFS_INDIRECT_PER_BLOCK,
816 // -------------------------------------------------------------------------
817 // findbuffer_indirect1()
818 // Indexes into an array of pointers to blocks containing pointers to
819 // blocks containing pointers to blocks (!) and extracts a pointer to
820 // the data at offset _pos_, allocating new blocks if required.
822 #if CYGNUM_RAMFS_BLOCKS_INDIRECT2 > 0
824 static int findbuffer_indirect2( off_t pos,
825 ramfs_block ****blocks,
831 int bi = pos / RAMFS_INDIRECT2_BLOCK_EXTENT;
832 int bpos = pos % RAMFS_INDIRECT2_BLOCK_EXTENT;
837 // Use findbuffer_direct() to index and allocate
838 // the first level indirect block.
840 err = findbuffer_direct( bi*CYGNUM_RAMFS_BLOCK_SIZE,
841 (ramfs_block **)blocks,
856 // Use findbuffer_indirect1() on the first level indirect block to
857 // index and allocate the next level indirect block and the data
860 return findbuffer_indirect1( bpos,
862 RAMFS_INDIRECT_PER_BLOCK,
870 // -------------------------------------------------------------------------
872 // Depending on the offset and configuration, call the appropriate
873 // function to get the buffer pointer.
875 static int findbuffer_node( ramfs_node *node,
881 #if CYGNUM_RAMFS_BLOCKS_DIRECT > 0
882 if( pos < RAMFS_DIRECT_MAX )
883 return findbuffer_direct( pos,
885 CYGNUM_RAMFS_BLOCKS_DIRECT,
890 #if CYGNUM_RAMFS_BLOCKS_INDIRECT1 > 0
891 if( pos < RAMFS_INDIRECT1_MAX )
892 return findbuffer_indirect1( pos - RAMFS_DIRECT_MAX,
894 CYGNUM_RAMFS_BLOCKS_INDIRECT1,
899 #if CYGNUM_RAMFS_BLOCKS_INDIRECT2 > 0
900 if( pos < RAMFS_INDIRECT2_MAX )
901 return findbuffer_indirect2( pos - RAMFS_INDIRECT1_MAX,
903 CYGNUM_RAMFS_BLOCKS_INDIRECT2,
912 // -------------------------------------------------------------------------
914 // Free a list of data blocks.
916 static void freeblock_list( ramfs_block *blocks[],int nblocks )
919 for( i = 0; i < nblocks ; i++ )
921 if( blocks[i] != NULL )
923 block_free( blocks[i] );
929 // -------------------------------------------------------------------------
931 // Free all the data blocks in the node and clear the pointers.
933 static int freebuffer_node( ramfs_node *node )
935 #if CYGNUM_RAMFS_BLOCKS_DIRECT > 0
936 freeblock_list( node->direct, CYGNUM_RAMFS_BLOCKS_DIRECT );
939 #if CYGNUM_RAMFS_BLOCKS_INDIRECT1 > 0
942 for( i = 0; i < CYGNUM_RAMFS_BLOCKS_INDIRECT1 ; i++ )
944 if( node->indirect1[i] != NULL )
946 freeblock_list( (ramfs_block **)node->indirect1[i], RAMFS_INDIRECT_PER_BLOCK );
947 block_free( (ramfs_block *)node->indirect1[i] );
948 node->indirect1[i] = NULL;
954 #if CYGNUM_RAMFS_BLOCKS_INDIRECT2 > 0
957 for( i = 0; i < CYGNUM_RAMFS_BLOCKS_INDIRECT2 ; i++ )
959 if( node->indirect2[i] != NULL )
961 ramfs_block ***b = node->indirect2[i];
963 for( j = 0; j < RAMFS_INDIRECT_PER_BLOCK ; j++ )
967 freeblock_list( (ramfs_block **)b[j], RAMFS_INDIRECT_PER_BLOCK );
968 block_free( (ramfs_block *)b[j] );
972 block_free( (ramfs_block *)node->indirect2[i] );
973 node->indirect2[i] = NULL;
982 //==========================================================================
986 //==========================================================================
989 // -------------------------------------------------------------------------
991 // Allocate a node and initialize it.
992 // For the _SIMPLE allocation option, we just malloc it. For the
993 // _BLOCKS option we allocate a block and use that. In theory we could
994 // pack several nodes into a single block, but we don't at present due
995 // to sheer lazyness.
997 static ramfs_node *alloc_node( mode_t mode )
999 #ifdef CYGPKG_FS_RAM_SIMPLE
1000 ramfs_node *node = malloc( sizeof( ramfs_node ) );
1006 ramfs_block *b = block_alloc();
1012 node = (ramfs_node *)b;
1016 memset( node, 0, sizeof(ramfs_node) );
1024 node->ctime = cyg_timestamp();
1026 #ifdef CYGPKG_FS_RAM_SIMPLE
1031 // The node is already all zero
1037 // -------------------------------------------------------------------------
1039 // Release a node either back to the free pool or back into the block
1042 static void free_node( ramfs_node *node )
1044 #ifdef CYGPKG_FS_RAM_SIMPLE
1050 block_free( (ramfs_block *)node );
1057 //==========================================================================
1058 // Ref count and nlink management
1060 // -------------------------------------------------------------------------
1062 // Decrment the reference count on a node. If this makes the ref count
1063 // zero, and the number of links is either zero for a file or one for
1064 // a node, then this node is detached from the directory tree and can
1067 static int dec_refcnt( ramfs_node *node )
1072 if( node->refcnt == 0 &&
1073 ((S_ISREG(node->mode) && node->nlink == 0 ) ||
1074 (S_ISDIR(node->mode) && node->nlink == 1) )
1077 // This node it now totally detached from the directory tree,
1080 if( S_ISDIR(node->mode) )
1082 del_direntry( node, ".", 1 );
1083 del_direntry( node, "..", 2 );
1086 err = freebuffer_node( node );
1095 // -------------------------------------------------------------------------
1097 // Decrement a node's link count. Since this has to do all the same
1098 // work as dec_refcnt() we implement this using that function by
1099 // essentially transferring the count to refcnt and then decrement
1102 static int dec_nlink( ramfs_node *node )
1108 return dec_refcnt( node );
1111 //==========================================================================
1112 // Directory operations
1114 // -------------------------------------------------------------------------
1116 // Add an entry to a directory. This is added as a chain of entry
1117 // fragments until the name is exhausted.
1119 static int add_direntry( ramfs_node *dir, // dir to add to
1120 const char *name, // name to add
1121 int namelen, // length of name
1122 ramfs_node *node // node to reference
1126 ramfs_dirent *d = NULL, *dp = NULL;
1127 cyg_bool isfirst = true;
1129 // Loop inserting fragments of the name into the directory until we
1130 // have found a home for them all.
1132 while( namelen > 0 )
1134 int fraglen = namelen;
1136 if( fraglen > sizeof(d->name) )
1137 fraglen = sizeof(d->name);
1139 // Find a free fragment
1144 int err = findbuffer_node( dir, pos, &buf, &size, true );
1145 if( err != ENOERR ) return err;
1147 d = (ramfs_dirent *)buf;
1149 if( size < sizeof(ramfs_dirent) || d->inuse )
1151 pos += sizeof(ramfs_dirent);
1158 // d now points to a free dirent structure
1163 d->namelen = namelen;
1164 d->fraglen = fraglen;
1165 if( dp ) dp->next = pos;
1167 memcpy( d->name, name, fraglen );
1171 pos += sizeof(ramfs_dirent);
1178 d->last = 1; // Mark last fragment
1180 // Update directory times
1182 dir->ctime = cyg_timestamp();
1184 // Extend dir size if necessary
1185 if( pos > dir->size )
1188 // Count the new link
1194 // -------------------------------------------------------------------------
1196 // Find a directory entry for the name and return a pointer to the first
1199 static ramfs_dirent *find_direntry( ramfs_node *dir, const char *name, int namelen )
1201 ramfs_dirent *first = NULL;
1205 // Loop over all the entries until a match is found or we run out
1207 while( pos < dir->size )
1209 const char *frag = name;
1214 // look for a first name fragment
1217 err = findbuffer_node( dir, pos, &buf, &size, false );
1218 if( err != ENOERR || size == 0)
1221 d = (ramfs_dirent *)buf;
1223 if( size < sizeof(ramfs_dirent) || !d->inuse || !d->first )
1225 pos += sizeof(ramfs_dirent);
1226 if ( pos < dir->size )
1228 // End if directory, didn't find it.
1235 // Here we have got a first fragment of a name, check it
1236 // against the name we are looking for. First check that they
1237 // are the same length.
1239 if( d->namelen == namelen )
1241 // We have a potential candidate here...
1243 first = d; // Save it for later
1245 // Now check that all the name fragments match
1248 int fraglen = namelen-(frag-name);
1250 if( fraglen > d->fraglen )
1251 fraglen = d->fraglen;
1253 // compare strings, if different, look for another
1254 if( memcmp( frag, d->name, fraglen ) != 0 ) {
1259 // If we are at the last fragment, then the whole name string
1260 // has matched and we have a successful search.
1265 // Otherwise move on to next entry in chain
1266 err = findbuffer_node( dir, d->next, &buf, &size, false );
1270 d = (ramfs_dirent *)buf;
1275 pos += sizeof(ramfs_dirent);
1281 // -------------------------------------------------------------------------
1283 // Delete a named directory entry. Find it and then follow the chain
1284 // deleting the fragments as we go.
1286 static int del_direntry( ramfs_node *dir, const char *name, int namelen )
1288 ramfs_dirent *d = find_direntry( dir, name, namelen );
1300 if( d->last ) break;
1302 err = findbuffer_node( dir, d->next, &buf, &size, false );
1306 d = (ramfs_dirent *)buf;
1309 dec_nlink( d->node );
1314 //==========================================================================
1317 // -------------------------------------------------------------------------
1319 // Initialize a dirsearch object to start a search
1321 static void init_dirsearch( ramfs_dirsearch *ds,
1333 // -------------------------------------------------------------------------
1335 // Search a single directory for the next name in a path and update the
1336 // dirsearch object appropriately.
1338 static int find_entry( ramfs_dirsearch *ds )
1340 ramfs_node *dir = ds->dir;
1341 const char *name = ds->path;
1342 const char *n = name;
1346 // check that we really have a directory
1347 if( !S_ISDIR(dir->mode) )
1350 // Isolate the next element of the path name.
1351 while( *n != '\0' && *n != '/' )
1354 // Check if this is the last path element.
1355 while( *n == '/') n++;
1359 // update name in dirsearch object
1361 ds->namelen = namelen;
1363 // Here we have the name and its length set up.
1364 // Search the directory for a matching entry
1366 d = find_direntry( dir, name, namelen );
1371 // pass back the node we have found
1378 // -------------------------------------------------------------------------
1380 // Main interface to directory search code. This is used in all file
1381 // level operations to locate the object named by the pathname.
1383 static int ramfs_find( ramfs_dirsearch *d )
1387 // Short circuit empty paths
1388 if( *(d->path) == '\0' )
1391 // iterate down directory tree until we find the object
1395 err = find_entry( d );
1403 // Update dirsearch object to search next directory.
1405 d->path += d->namelen;
1406 while( *(d->path) == '/' ) d->path++; // skip dirname separators
1410 //==========================================================================
1412 // This function provides support for pathconf() and fpathconf().
1414 static int ramfs_pathconf( ramfs_node *node, struct cyg_pathconf_info *info )
1418 switch( info->name )
1421 info->value = LINK_MAX;
1425 info->value = -1; // not supported
1430 info->value = -1; // not supported
1435 info->value = NAME_MAX;
1439 info->value = PATH_MAX;
1443 info->value = -1; // not supported
1449 info->value = -1; // not supported
1453 case _PC_CHOWN_RESTRICTED:
1454 info->value = -1; // not supported
1471 info->value = -1; // not supported
1483 //==========================================================================
1484 // Filesystem operations
1486 // -------------------------------------------------------------------------
1488 // Process a mount request. This mainly creates a root for the
1491 static int ramfs_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte )
1496 // Allocate a node to be the root of this filesystem and initialize it.
1498 root = alloc_node(__stat_mode_DIR|S_IRWXU|S_IRWXG|S_IRWXO);
1503 // Add . and .. entries back to self.
1505 err = add_direntry( root, ".", 1, root );
1507 err = add_direntry( root, "..", 2, root );
1515 mte->root = (cyg_dir)root;
1520 // -------------------------------------------------------------------------
1522 // Unmount the filesystem. This will currently only succeed if the
1523 // filesystem is empty.
1525 static int ramfs_umount ( cyg_mtab_entry *mte )
1527 ramfs_node *root = (ramfs_node *)mte->root;
1529 // Check for open/inuse root
1530 if( root->refcnt != 0 )
1533 // Check that root directory is clear of extra links.
1534 if( root->nlink != 2 )
1537 // Just return it to free pool
1540 // Clear root pointer
1541 mte->root = CYG_DIR_NULL;
1543 // That's all folks.
1548 // -------------------------------------------------------------------------
1550 // Open a file for reading or writing.
1552 static int ramfs_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1553 int mode, cyg_file *file )
1557 ramfs_node *node = NULL;
1560 init_dirsearch( &ds, (ramfs_node *)dir, name );
1562 err = ramfs_find( &ds );
1566 if( ds.last && (mode & O_CREAT) )
1568 // No node there, if the O_CREAT bit is set then we must
1569 // create a new one. The dir and name fields of the dirsearch
1570 // object will have been updated so we know where to put it.
1572 node = alloc_node( __stat_mode_REG|S_IRWXU|S_IRWXG|S_IRWXO);
1577 err = add_direntry( ds.dir, ds.name, ds.namelen, node );
1588 else if( err == ENOERR )
1590 // The node exists. If the O_CREAT and O_EXCL bits are set, we
1591 // must fail the open.
1593 if( (mode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) )
1595 else node = ds.node;
1598 if( err == ENOERR && (mode & O_TRUNC ) )
1600 // If the O_TRUNC bit is set we must clean out the file data.
1602 err = freebuffer_node( node );
1605 // Update file times
1607 node->mtime = cyg_timestamp();
1610 if( err != ENOERR ) return err;
1612 // Check that we actually have a file here
1613 if( S_ISDIR(node->mode) ) return EISDIR;
1615 node->refcnt++; // Count successful open
1617 // Initialize the file object
1619 file->f_flag |= mode & CYG_FILE_MODE_MASK;
1620 file->f_type = CYG_FILE_TYPE_FILE;
1621 file->f_ops = &ramfs_fileops;
1622 file->f_offset = (mode&O_APPEND) ? node->size : 0;
1623 file->f_data = (CYG_ADDRWORD)node;
1629 // -------------------------------------------------------------------------
1631 // Remove a file link from its directory.
1633 static int ramfs_unlink ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
1638 init_dirsearch( &ds, (ramfs_node *)dir, name );
1640 err = ramfs_find( &ds );
1642 if( err != ENOERR ) return err;
1644 // Cannot unlink directories, use rmdir() instead
1645 if( S_ISDIR(ds.node->mode) )
1648 // Delete it from its directory
1649 err = del_direntry( ds.dir, ds.name, ds.namelen );
1654 // -------------------------------------------------------------------------
1656 // Create a new directory.
1658 static int ramfs_mkdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
1661 ramfs_node *node = NULL;
1664 init_dirsearch( &ds, (ramfs_node *)dir, name );
1666 err = ramfs_find( &ds );
1672 // The entry does not exist, and it is the last element in
1673 // the pathname, so we can create it here.
1674 int doterr, dotdoterr, direrr;
1676 node = alloc_node( __stat_mode_DIR | S_IRWXU|S_IRWXG|S_IRWXO);
1681 // Add "." and ".." entries.
1682 doterr = add_direntry( node, ".", 1, node );
1683 dotdoterr = add_direntry( node, "..", 2, ds.dir );
1685 // And add to parent directory.
1686 direrr = add_direntry( ds.dir, ds.name, ds.namelen, node );
1688 // check for any errors in that...
1689 if( doterr+dotdoterr+direrr != ENOERR )
1691 // For each of the add_direntry() calls that succeeded,
1692 // we must now undo it.
1694 if( doterr == ENOERR )
1695 del_direntry( node, ".", 1 );
1698 if( dotdoterr == ENOERR )
1699 del_direntry( node, "..", 2 );
1700 else err = dotdoterr;
1702 if( direrr == ENOERR )
1703 del_direntry( ds.dir, ds.name, ds.namelen );
1706 // Free the data and the node itself.
1707 freebuffer_node( node );
1712 // If this was not the last element, then and intermediate
1713 // directory does not exist.
1717 // If there we no error, something already exists with that
1718 // name, so we cannot create another one.
1727 // -------------------------------------------------------------------------
1729 // Remove a directory.
1731 static int ramfs_rmdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
1736 init_dirsearch( &ds, (ramfs_node *)dir, name );
1738 err = ramfs_find( &ds );
1740 if( err != ENOERR ) return err;
1742 // Check that this is actually a directory.
1743 if( !S_ISDIR(ds.node->mode) )
1746 // Delete the entry. This will adjust the link values
1747 // accordingly and if the directory is now unreferenced,
1748 // will cause it to be deleted.
1750 err = del_direntry( ds.dir, ds.name, ds.namelen );
1755 // -------------------------------------------------------------------------
1757 // Rename a file/dir.
1759 static int ramfs_rename ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
1760 cyg_dir dir2, const char *name2 )
1762 ramfs_dirsearch ds1, ds2;
1765 init_dirsearch( &ds1, (ramfs_node *)dir1, name1 );
1767 err = ramfs_find( &ds1 );
1769 if( err != ENOERR ) return err;
1771 init_dirsearch( &ds2, (ramfs_node *)dir2, name2 );
1773 err = ramfs_find( &ds2 );
1775 // Allow through renames to non-existent objects.
1776 if( ds2.last && err == ENOENT )
1777 ds2.node = NULL, err = ENOERR;
1779 if( err != ENOERR ) return err;
1781 // Null rename, just return
1782 if( ds1.node == ds2.node )
1785 // First deal with any entry that is at the destination
1788 // Check that we are renaming like-for-like
1790 if( !S_ISDIR(ds1.node->mode) && S_ISDIR(ds2.node->mode) )
1793 if( S_ISDIR(ds1.node->mode) && !S_ISDIR(ds2.node->mode) )
1796 // Now delete the destination directory entry
1798 err = del_direntry( ds2.dir, ds2.name, ds2.namelen );
1800 if( err != ENOERR ) return err;
1804 // Now we know that there is no clashing node at the destination,
1805 // make a new direntry at the destination and delete the old entry
1808 err = add_direntry( ds2.dir, ds2.name, ds2.namelen, ds1.node );
1811 err = del_direntry( ds1.dir, ds1.name, ds1.namelen );
1813 // Update directory times
1818 ds2.dir->mtime = cyg_timestamp();
1823 // -------------------------------------------------------------------------
1825 // Make a new directory entry for a file.
1827 static int ramfs_link ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
1828 cyg_dir dir2, const char *name2, int type )
1830 ramfs_dirsearch ds1, ds2;
1833 // Only do hard links for now in this filesystem
1834 if( type != CYG_FSLINK_HARD )
1837 init_dirsearch( &ds1, (ramfs_node *)dir1, name1 );
1839 err = ramfs_find( &ds1 );
1841 if( err != ENOERR ) return err;
1843 init_dirsearch( &ds2, (ramfs_node *)dir2, name2 );
1845 err = ramfs_find( &ds2 );
1847 // Don't allow links to existing objects
1848 if( err == ENOERR ) return EEXIST;
1850 // Allow through links to non-existing terminal objects
1851 if( ds2.last && err == ENOENT )
1852 ds2.node = NULL, err = ENOERR;
1854 if( err != ENOERR ) return err;
1856 // Now we know that there is no existing node at the destination,
1857 // make a new direntry at the destination.
1859 err = add_direntry( ds2.dir, ds2.name, ds2.namelen, ds1.node );
1864 ds2.dir->mtime = cyg_timestamp();
1869 // -------------------------------------------------------------------------
1871 // Open a directory for reading.
1873 static int ramfs_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1879 init_dirsearch( &ds, (ramfs_node *)dir, name );
1881 err = ramfs_find( &ds );
1883 if( err != ENOERR ) return err;
1885 // check it is really a directory.
1886 if( !S_ISDIR(ds.node->mode) ) return ENOTDIR;
1888 ds.node->refcnt++; // Count successful open
1890 // Initialize the file object, setting the f_ops field to a
1891 // special set of file ops.
1893 file->f_type = CYG_FILE_TYPE_FILE;
1894 file->f_ops = &ramfs_dirops;
1896 file->f_data = (CYG_ADDRWORD)ds.node;
1903 // -------------------------------------------------------------------------
1905 // Change directory support.
1907 static int ramfs_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1910 if( dir_out != NULL )
1912 // This is a request to get a new directory pointer in
1918 init_dirsearch( &ds, (ramfs_node *)dir, name );
1920 err = ramfs_find( &ds );
1922 if( err != ENOERR ) return err;
1924 // check it is a directory
1925 if( !S_ISDIR(ds.node->mode) )
1928 // Increment ref count to keep this directory in existent
1929 // while it is the current cdir.
1933 *dir_out = (cyg_dir)ds.node;
1937 // If no output dir is required, this means that the mte and
1938 // dir arguments are the current cdir setting and we should
1939 // forget this fact.
1941 ramfs_node *node = (ramfs_node *)dir;
1943 // Just decrement directory reference count.
1950 // -------------------------------------------------------------------------
1952 // Get struct stat info for named object.
1954 static int ramfs_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1960 init_dirsearch( &ds, (ramfs_node *)dir, name );
1962 err = ramfs_find( &ds );
1964 if( err != ENOERR ) return err;
1966 // Fill in the status
1967 buf->st_mode = ds.node->mode;
1968 buf->st_ino = (ino_t)ds.node;
1970 buf->st_nlink = ds.node->nlink;
1973 buf->st_size = ds.node->size;
1974 buf->st_atime = ds.node->atime;
1975 buf->st_mtime = ds.node->mtime;
1976 buf->st_ctime = ds.node->ctime;
1981 // -------------------------------------------------------------------------
1983 // Getinfo. Currently only support pathconf() and filesystem usage.
1985 static int ramfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1986 int key, void *buf, int len )
1991 init_dirsearch( &ds, (ramfs_node *)dir, name );
1993 err = ramfs_find( &ds );
1995 if( err != ENOERR ) return err;
2000 err = ramfs_pathconf( ds.node, (struct cyg_pathconf_info *)buf );
2002 #if defined(CYGSEM_FILEIO_BLOCK_USAGE) && defined(CYGPKG_FS_RAM_BLOCKS_ARRAY)
2003 // When using malloc for storage this does not make much
2004 // sense, so only implement this when using pre-allocated
2006 case FS_INFO_BLOCK_USAGE: {
2007 struct cyg_fs_block_usage *usage = (struct cyg_fs_block_usage *) buf;
2010 usage->total_blocks = CYGNUM_FS_RAM_BLOCKS_ARRAY_SIZE;
2011 usage->free_blocks = 0;
2012 // Iterate over the free list to count its size
2013 b = block_free_list;
2015 usage->free_blocks++;
2016 b=*(ramfs_block **)b;
2018 usage->block_size = CYGNUM_RAMFS_BLOCK_SIZE;
2028 // -------------------------------------------------------------------------
2030 // Setinfo. Nothing to support here at present.
2032 static int ramfs_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2033 int key, void *buf, int len )
2035 // No setinfo keys supported at present
2041 //==========================================================================
2044 // -------------------------------------------------------------------------
2046 // Read data from the file.
2048 static int ramfs_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2050 ramfs_node *node = (ramfs_node *)fp->f_data;
2052 off_t pos = fp->f_offset;
2053 ssize_t resid = uio->uio_resid;
2055 // Loop over the io vectors until there are none left
2056 for( i = 0; i < uio->uio_iovcnt; i++ )
2058 cyg_iovec *iov = &uio->uio_iov[i];
2059 char *buf = (char *)iov->iov_base;
2060 off_t len = iov->iov_len;
2062 // Loop over each vector filling it with data from the file.
2063 while( len > 0 && pos < node->size )
2070 // Get a pointer to the data at offset _pos_.
2071 err = findbuffer_node( node, pos, &fbuf, &bsize, false );
2076 // adjust size to end of file if necessary
2077 if( l > node->size-pos )
2080 // adjust size to the amount of contiguous data we can see
2087 memcpy( buf, fbuf, l );
2088 } else { // hole, so return zeros here.
2089 memset( buf, 0, l );
2092 // Update working vars
2100 // We successfully read some data, update the node's access time
2101 // and update the file offset and transfer residue.
2103 node->atime = cyg_timestamp();
2105 uio->uio_resid = resid;
2111 // -------------------------------------------------------------------------
2113 // Write data to file.
2115 static int ramfs_fo_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2117 ramfs_node *node = (ramfs_node *)fp->f_data;
2118 off_t pos = fp->f_offset;
2119 ssize_t resid = uio->uio_resid;
2123 // If the APPEND mode bit was supplied, force all writes to
2124 // the end of the file.
2125 if( fp->f_flag & CYG_FAPPEND )
2126 pos = fp->f_offset = node->size;
2128 // Now loop over the iovecs until they are all done, or
2130 for( i = 0; i < uio->uio_iovcnt; i++ )
2132 cyg_iovec *iov = &uio->uio_iov[i];
2133 char *buf = (char *)iov->iov_base;
2134 off_t len = iov->iov_len;
2136 // loop over the vector writing it to the file until it has
2144 err = findbuffer_node( node, pos, &fbuf, &bsize, true );
2146 // Stop writing if there is no more space in the file and
2147 // indicate end of data.
2154 // adjust size to this block
2159 memcpy( fbuf, buf, l );
2161 // Update working vars
2169 // We wrote some data successfully, update the modified and access
2170 // times of the node, increase its size appropriately, and update
2171 // the file offset and transfer residue.
2173 node->ctime = cyg_timestamp();
2174 if( pos > node->size )
2177 uio->uio_resid = resid;
2183 // -------------------------------------------------------------------------
2185 // Seek to a new file position.
2187 static int ramfs_fo_lseek (struct CYG_FILE_TAG *fp, off_t *apos, int whence )
2189 ramfs_node *node = (ramfs_node *)fp->f_data;
2195 // Pos is already where we want to be.
2199 // Add pos to current offset.
2200 pos += fp->f_offset;
2204 // Add pos to file size.
2212 // All OK, set fp offset and return new position.
2213 *apos = fp->f_offset = pos;
2218 // -------------------------------------------------------------------------
2220 // Handle ioctls. Currently none are defined.
2222 static int ramfs_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
2225 // No Ioctls currenly defined.
2230 // -------------------------------------------------------------------------
2231 // ramfs_fo_fsync().
2232 // Force the file out to data storage.
2234 static int ramfs_fo_fsync (struct CYG_FILE_TAG *fp, int mode )
2236 // Data is always permanently where it belongs, nothing to do
2242 // -------------------------------------------------------------------------
2244 // Close a file. We just decrement the refcnt and let it go away if
2245 // that is all that is keeping it here.
2247 static int ramfs_fo_close (struct CYG_FILE_TAG *fp)
2249 ramfs_node *node = (ramfs_node *)fp->f_data;
2253 fp->f_data = 0; // zero data pointer
2258 // -------------------------------------------------------------------------
2262 static int ramfs_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf )
2264 ramfs_node *node = (ramfs_node *)fp->f_data;
2266 // Fill in the status
2267 buf->st_mode = node->mode;
2268 buf->st_ino = (ino_t)node;
2270 buf->st_nlink = node->nlink;
2273 buf->st_size = node->size;
2274 buf->st_atime = node->atime;
2275 buf->st_mtime = node->mtime;
2276 buf->st_ctime = node->ctime;
2281 // -------------------------------------------------------------------------
2282 // ramfs_fo_getinfo()
2283 // Get info. Currently only supports fpathconf().
2285 static int ramfs_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
2287 ramfs_node *node = (ramfs_node *)fp->f_data;
2293 err = ramfs_pathconf( node, (struct cyg_pathconf_info *)buf );
2302 // -------------------------------------------------------------------------
2303 // ramfs_fo_setinfo()
2304 // Set info. Nothing supported here.
2306 static int ramfs_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
2308 // No setinfo key supported at present
2314 //==========================================================================
2315 // Directory operations
2317 // -------------------------------------------------------------------------
2318 // ramfs_fo_dirread()
2319 // Read a single directory entry from a file.
2321 static int ramfs_fo_dirread (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2323 ramfs_node *dir = (ramfs_node *)fp->f_data;
2324 off_t pos = fp->f_offset;
2326 struct dirent *ent = (struct dirent *)uio->uio_iov[0].iov_base;
2327 char *nbuf = ent->d_name;
2328 int nlen = sizeof(ent->d_name)-1;
2329 off_t len = uio->uio_iov[0].iov_len;
2330 ramfs_dirent *d = NULL;
2334 if( len < sizeof(struct dirent) )
2337 // look for a first name fragment
2339 while( pos < dir->size )
2341 err = findbuffer_node( dir, pos, &buf, &size, false );
2342 if( err != ENOERR || size == 0)
2345 d = (ramfs_dirent *)buf;
2347 if( size < sizeof(ramfs_dirent) || !d->inuse || !d->first )
2349 pos += sizeof(ramfs_dirent);
2356 // Check we have not exceeded the size of the directory.
2357 if( pos == dir->size )
2360 // Here we have the first fragment of a directory entry.
2364 int fraglen = d->fraglen;
2366 // adjust to allow for remaining space in dirent struct
2367 if( fraglen > nlen )
2370 memcpy( nbuf, d->name, fraglen);
2373 #ifdef CYGPKG_FS_RAM_RET_DIRENT_DTYPE
2374 ent->d_type = d->node->mode;
2377 // if we hit the last entry, we have a successful transfer
2378 if( d->last || nlen == 0)
2381 // Otherwise move on to next entry in chain
2382 err = findbuffer_node( dir, d->next, &buf, &size, false );
2386 d = (ramfs_dirent *)buf;
2389 // A successful read. Terminate the entry name with a NUL, set the
2390 // residue and set the file offset to restart at the next
2394 uio->uio_resid -= sizeof(struct dirent);
2395 fp->f_offset = pos+sizeof(ramfs_dirent);
2400 // -------------------------------------------------------------------------
2401 // ramfs_fo_dirlseek()
2402 // Seek directory to start.
2404 static int ramfs_fo_dirlseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence )
2406 // Only allow SEEK_SET to zero
2408 if( whence != SEEK_SET || *pos != 0)
2411 *pos = fp->f_offset = 0;
2416 // -------------------------------------------------------------------------