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, richard.panton@3glab.com
46 // Purpose: ROM file system
47 // Description: This is a ROM 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 ROM 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 // There is a single header that describes the overall format of the ROMFS
70 // disk. The address of this header is used as the base for all offsets used
71 // in the node and directory structures. It contains the following fields:
73 // label - A human readable label for various purposes
74 // fssize - The size in bytes of the entire ROMFS disk
75 // nodes - A count of the nodes in the disk
77 // Immediately following thisin memory is the node table, consisting of
78 // 'nodes' repetitions of the node object.
83 // All files and directories are represented by node objects. Each
84 // romfs_node structure contains the following fields:
86 // mode - Node type, file or directory.
87 // nlink - Number of links to this node. Each directory entry that references
88 // this node is a link.
89 // size - Size of the data in this node in bytes.
90 // ctime - Creation time of the file (NOT the ROMFS)
91 // data - Offset of the first data byte for this node from the header
96 // A directory is a node whose data is a list of directory entries.
100 // node - Index of the node in the romfs_disk table that is referenced by
101 // this entry. This is present in every directory entry fragment.
102 // next - Offset of the next name entry.
103 // name - The filename associated with this link to the node.
108 // Each file has its data stored in a single contiguous memory block
109 // referenced by the offset in the node.
111 //==========================================================================
113 #include <pkgconf/system.h>
114 #include <pkgconf/hal.h>
115 #include <pkgconf/kernel.h>
116 #include <pkgconf/io_fileio.h>
117 #include <pkgconf/fs_rom.h>
119 #include <cyg/kernel/ktypes.h> // base kernel types
120 #include <cyg/infra/cyg_trac.h> // tracing macros
121 #include <cyg/infra/cyg_ass.h> // assertion macros
124 #include <sys/types.h>
126 #include <sys/stat.h>
135 #include <cyg/fileio/fileio.h>
137 #include <cyg/kernel/kapi.h>
138 #include <cyg/infra/diag.h>
140 //==========================================================================
141 // Eventually we want to eXecute In Place from the ROM in a protected
142 // environment, so we'll need executables to be aligned to a boundary
143 // suitable for MMU protection. A suitable boundary would be the 4k
144 // boundary in all the CPU architectures I am currently aware of.
146 // Forward definitions
148 // Filesystem operations
149 static int romfs_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte );
150 static int romfs_umount ( cyg_mtab_entry *mte );
151 static int romfs_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
152 int mode, cyg_file *fte );
153 static int romfs_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
155 static int romfs_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
157 static int romfs_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
159 static int romfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
160 int key, void *buf, int len );
161 static int romfs_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
162 int key, void *buf, int len );
165 static int romfs_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
166 static int romfs_fo_lseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
167 static int romfs_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
169 static int romfs_fo_fsync (struct CYG_FILE_TAG *fp, int mode );
170 static int romfs_fo_close (struct CYG_FILE_TAG *fp);
171 static int romfs_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf );
172 static int romfs_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
173 static int romfs_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
175 // Directory operations
176 static int romfs_fo_dirread (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
177 static int romfs_fo_dirlseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
180 //==========================================================================
181 // Filesystem table entries
183 // -------------------------------------------------------------------------
185 // This defines the entry in the filesystem table.
186 // For simplicity we use _FILESYSTEM synchronization for all accesses since
187 // we should never block in any filesystem operations.
189 FSTAB_ENTRY( romfs_fste, "romfs", 0,
190 CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,
194 (cyg_fsop_unlink *)cyg_fileio_erofs,
195 (cyg_fsop_mkdir *)cyg_fileio_erofs,
196 (cyg_fsop_rmdir *)cyg_fileio_erofs,
197 (cyg_fsop_rename *)cyg_fileio_erofs,
198 (cyg_fsop_link *)cyg_fileio_erofs,
205 // -------------------------------------------------------------------------
207 // This defines a single ROMFS loaded into ROM at the configured address
209 // MTAB_ENTRY( rom_mte, // structure name
210 // "/rom", // mount point
211 // "romfs", // FIlesystem type
212 // "", // hardware device
213 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
217 // -------------------------------------------------------------------------
219 // This set of file operations are used for normal open files.
221 static cyg_fileops romfs_fileops =
224 (cyg_fileop_write *)cyg_fileio_erofs,
235 // -------------------------------------------------------------------------
236 // Directory file operations.
237 // This set of operations are used for open directories. Most entries
238 // point to error-returning stub functions. Only the read, lseek and
239 // close entries are functional.
241 static cyg_fileops romfs_dirops =
244 (cyg_fileop_write *)cyg_fileio_enosys,
246 (cyg_fileop_ioctl *)cyg_fileio_enosys,
248 (cyg_fileop_fsync *)cyg_fileio_enosys,
250 (cyg_fileop_fstat *)cyg_fileio_enosys,
251 (cyg_fileop_getinfo *)cyg_fileio_enosys,
252 (cyg_fileop_setinfo *)cyg_fileio_enosys
255 //==========================================================================
257 // Some forward typedefs for the main data structures.
260 typedef struct romfs_disk romfs_disk;
263 typedef struct romfs_node romfs_node;
266 typedef struct romfs_dirent romfs_dirent;
268 //==========================================================================
269 // File and directory node
270 // This data structure represents a file or directory.
274 cyg_uint32 mode; // 0-3 node type
275 cyg_ucount32 nlink; // 4-7 number of links to this node
276 cyg_uint16 uid; // 8-9 Owner id
277 cyg_uint16 gid; // 10-11 Group id
278 cyg_uint32 size; // 12-15 size of file in bytes
279 cyg_uint32 ctime; // 16-19 creation status time
280 cyg_uint32 offset; // 20-23 offset of data from start of ROMFS
281 cyg_uint32 pad[2]; // 24-31 padding to align to 32byte boundary
284 //==========================================================================
286 // Variable sized entry containing the name and node of a directory entry
290 cyg_ucount32 node; // Index of node in romfs_disk structure
291 cyg_uint32 next; // Offset from start of directory of
292 // a) the next entry, or
293 // b) the end of the directory data
294 char name[0]; // The name, NUL terminated
297 //==========================================================================
299 // This data structure contains overall information on the ROMFS
303 cyg_uint32 magic; // 0-3 Marks a valid ROMFS entry
304 cyg_ucount32 nodecount; // 4-7 Count of nodes in this filesystem
305 cyg_ucount32 disksize; // 8-11 Count of bytes in this filesystem
306 cyg_uint32 dev_id; // 12-15 ID of disk (put into stat.st_dev)
307 char name[16]; // 16-31 Name - pads to 32 bytes
311 #define ROMFS_MAGIC 0x526f6d2e // The magic signature word for a romfs
312 #define ROMFS_CIGAM 0x2e6d6f52 // The byte sex is wrong if you see this
314 //==========================================================================
315 // Directory search data
316 // Parameters for a directory search. The fields of this structure are
317 // updated as we follow a pathname through the directory tree.
319 struct romfs_dirsearch
321 romfs_disk *disk; // disk structure
322 romfs_node *dir; // directory to search
323 const char *path; // path to follow
324 romfs_node *node; // Node found
325 const char *name; // last name used
326 int namelen; // name fragment length
327 cyg_bool last; // last name in path?
330 typedef struct romfs_dirsearch romfs_dirsearch;
332 //==========================================================================
333 // This seems to be the only string function referenced. Define as static
334 // here to avoid having to load the string library
336 static bool match( const char *a, const char *b, int len )
338 for ( ; len > 0 && *a && *b && *a == *b ; a++, b++, len-- )
344 //==========================================================================
345 // SIMPLE buffer management.
346 // Each node has a data buffer pointer and a size.
348 // -------------------------------------------------------------------------
350 // return a pointer to the data at the indicated file position.
352 static int findbuffer_node( romfs_disk *disk, // header pointer
353 romfs_node *node, // node pointer
354 off_t pos, // data position to get
355 cyg_uint8 **buffer, // returned buffer pointer
356 size_t *size) // returned buffer size
358 if ( pos >= node->size || node->size == 0 )
360 // Indicate end of data.
364 // Calculate the buffer position
365 *buffer = (cyg_uint8*)disk + node->offset + pos;
366 *size = node->size-pos;
372 //==========================================================================
373 // Directory operations
376 // -------------------------------------------------------------------------
378 // Find a directory entry for the name and return a pointer to the first
381 static romfs_dirent *find_direntry( romfs_disk *disk, romfs_node *dir, const char *name, int namelen )
386 // Loop over all the entries until a match is found or we run out
388 while( pos < dir->size )
394 err = findbuffer_node( disk, dir, pos, &buf, &size );
395 if( err != ENOERR || size == 0)
398 d = (romfs_dirent *)buf;
400 // Is this the directory entry we're looking for?
401 if ( match( d->name, name, namelen ) )
404 // Otherwise move on to next entry in chain
411 //==========================================================================
414 // -------------------------------------------------------------------------
416 // Initialize a dirsearch object to start a search
418 static void init_dirsearch( romfs_dirsearch *ds,
432 // -------------------------------------------------------------------------
434 // Search a single directory for the next name in a path and update the
435 // dirsearch object appropriately.
437 static int find_entry( romfs_dirsearch *ds )
439 romfs_node *dir = ds->dir;
440 const char *name = ds->path;
441 const char *n = name;
445 // check that we really have a directory
446 if( !S_ISDIR(dir->mode) )
449 // Isolate the next element of the path name.
450 while( *n != '\0' && *n != '/' )
453 // Check if this is the last path element.
454 while( *n == '/') n++;
458 // update name in dirsearch object
460 ds->namelen = namelen;
462 // Here we have the name and its length set up.
463 // Search the directory for a matching entry
465 d = find_direntry( ds->disk, dir, name, namelen );
470 // pass back the node we have found
471 ds->node = &ds->disk->node[d->node];
477 // -------------------------------------------------------------------------
479 // Main interface to directory search code. This is used in all file
480 // level operations to locate the object named by the pathname.
482 static int romfs_find( romfs_dirsearch *d )
486 // Short circuit empty paths
487 if( *(d->path) == '\0' )
490 // iterate down directory tree until we find the object
494 err = find_entry( d );
502 // Update dirsearch object to search next directory.
504 d->path += d->namelen;
505 while( *(d->path) == '/' ) d->path++; // skip dirname separators
509 //==========================================================================
511 // This function provides support for pathconf() and fpathconf().
513 static int romfs_pathconf( romfs_node *node, struct cyg_pathconf_info *info )
520 info->value = LINK_MAX;
524 info->value = -1; // not supported
529 info->value = -1; // not supported
534 info->value = NAME_MAX;
538 info->value = PATH_MAX;
542 info->value = -1; // not supported
548 info->value = -1; // not supported
552 case _PC_CHOWN_RESTRICTED:
553 info->value = -1; // not supported
570 info->value = -1; // not supported
582 //==========================================================================
583 // Filesystem operations
585 // -------------------------------------------------------------------------
587 // Process a mount request. This mainly finds root for the
590 static int romfs_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte )
592 romfs_disk *disk=NULL;
595 // If the image address was not in the MTE data word,
596 if ( mte->devname && mte->devname[0] ) {
598 // And there's something in the 'hardware device' field,
599 // then read the address from there.
600 sscanf( mte->devname, "%p", &addr );
601 disk = (romfs_disk *) addr;
604 disk = (romfs_disk *)mte->data;
608 // If still no address, try the FSTAB entry data word
609 disk = (romfs_disk *)fste->data;
613 // If still no address, give up...
619 // Check the ROMFS magic number to ensure that there's really an fs.
620 if ( disk->magic == ROMFS_CIGAM ) {
621 // The disk image has the wrong byte sex!!!
623 } else if ( disk->magic != ROMFS_MAGIC || disk->nodecount == 0 ) {
628 mte->root = (cyg_dir)&disk->node[0];
630 mte->data = (CYG_ADDRWORD)disk;
634 // -------------------------------------------------------------------------
636 // Unmount the filesystem. This will currently always succeed.
638 static int romfs_umount ( cyg_mtab_entry *mte )
640 // Clear root pointer
641 mte->root = CYG_DIR_NULL;
648 // -------------------------------------------------------------------------
650 // Open a file for reading
652 static int romfs_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
653 int mode, cyg_file *file )
657 romfs_node *node = NULL;
660 init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name );
662 err = romfs_find( &ds );
668 else if( err == ENOERR )
670 // The node exists. If the O_CREAT and O_EXCL bits are set, we
671 // must fail the open.
673 if( (mode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) )
678 if( err == ENOERR && (mode & O_TRUNC ) )
680 // If the O_TRUNC bit is set we must fail the open
685 if( err != ENOERR ) return err;
687 // Check that we actually have a file here
688 if( S_ISDIR(node->mode) ) return EISDIR;
690 // Initialize the file object
692 file->f_flag |= mode & CYG_FILE_MODE_MASK;
693 file->f_type = CYG_FILE_TYPE_FILE;
694 file->f_ops = &romfs_fileops;
696 file->f_data = (CYG_ADDRWORD)node;
702 // -------------------------------------------------------------------------
704 // Open a directory for reading.
706 static int romfs_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
712 init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name );
714 err = romfs_find( &ds );
716 if( err != ENOERR ) return err;
718 // check it is really a directory.
719 if( !S_ISDIR(ds.node->mode) ) return ENOTDIR;
721 // Initialize the file object, setting the f_ops field to a
722 // special set of file ops.
724 file->f_type = CYG_FILE_TYPE_FILE;
725 file->f_ops = &romfs_dirops;
727 file->f_data = (CYG_ADDRWORD)ds.node;
734 // -------------------------------------------------------------------------
736 // Change directory support.
738 static int romfs_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
741 if( dir_out != NULL )
743 // This is a request to get a new directory pointer in
749 init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name );
751 err = romfs_find( &ds );
753 if( err != ENOERR ) return err;
755 // check it is a directory
756 if( !S_ISDIR(ds.node->mode) )
760 *dir_out = (cyg_dir)ds.node;
762 // If no output dir is required, this means that the mte and
763 // dir arguments are the current cdir setting and we should
764 // forget this fact. Do nothing in ROMFS.
769 // -------------------------------------------------------------------------
771 // Get struct stat info for named object.
773 static int romfs_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
778 romfs_disk *disk = (romfs_disk *)mte->data;
780 init_dirsearch( &ds, disk, (romfs_node *)dir, name );
782 err = romfs_find( &ds );
784 if( err != ENOERR ) return err;
786 // Fill in the status
787 buf->st_mode = ds.node->mode;
788 buf->st_ino = (ino_t)(ds.node - &disk->node[0]);
789 buf->st_dev = (dev_t)disk->dev_id;
790 buf->st_nlink = ds.node->nlink;
791 buf->st_uid = ds.node->uid;
792 buf->st_gid = ds.node->gid;
793 buf->st_size = ds.node->size;
794 buf->st_atime = ds.node->ctime;
795 buf->st_mtime = ds.node->ctime;
796 buf->st_ctime = ds.node->ctime;
801 // -------------------------------------------------------------------------
803 // Getinfo. Currently only support pathconf() and file system block usage
805 static int romfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
806 int key, void *buf, int len )
811 init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name );
813 err = romfs_find( &ds );
815 if( err != ENOERR ) return err;
820 err = romfs_pathconf( ds.node, (struct cyg_pathconf_info *)buf );
822 #if defined(CYGSEM_FILEIO_BLOCK_USAGE)
823 case FS_INFO_BLOCK_USAGE: {
824 struct cyg_fs_block_usage *usage = (struct cyg_fs_block_usage *) buf;
825 struct romfs_disk *disk = (struct romfs_disk*) mte->data;
826 usage->total_blocks = disk->disksize;
827 usage->free_blocks = 0;
828 usage->block_size = 1;
838 // -------------------------------------------------------------------------
840 // Setinfo. Nothing to support here at present.
842 static int romfs_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
843 int key, void *buf, int len )
845 // No setinfo keys supported at present
851 //==========================================================================
854 // -------------------------------------------------------------------------
856 // Read data from the file.
858 static int romfs_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
860 romfs_node *node = (romfs_node *)fp->f_data;
862 off_t pos = fp->f_offset;
863 ssize_t resid = uio->uio_resid;
865 // Loop over the io vectors until there are none left
866 for( i = 0; i < uio->uio_iovcnt; i++ )
868 cyg_iovec *iov = &uio->uio_iov[i];
869 char *buf = (char *)iov->iov_base;
870 off_t len = iov->iov_len;
872 // Loop over each vector filling it with data from the file.
873 while( len > 0 && pos < node->size )
880 // Get a pointer to the data at offset _pos_.
881 err = findbuffer_node( (romfs_disk *)fp->f_mte->data, node, pos, &fbuf, &bsize );
886 // adjust size to end of file if necessary
887 if( l > node->size-pos )
890 // adjust size to the amount of contiguous data we can see
896 memcpy( buf, fbuf, l );
898 // Update working vars
906 // We successfully read some data
907 // Update the file offset and transfer residue.
909 uio->uio_resid = resid;
915 // -------------------------------------------------------------------------
917 // Seek to a new file position.
919 static int romfs_fo_lseek (struct CYG_FILE_TAG *fp, off_t *apos, int whence )
921 romfs_node *node = (romfs_node *)fp->f_data;
927 // Pos is already where we want to be.
931 // Add pos to current offset.
936 // Add pos to file size.
944 // Check that pos is still within current file size, or at the
946 if( pos < 0 || pos > node->size )
949 // All OK, set fp offset and return new position.
950 *apos = fp->f_offset = pos;
955 // -------------------------------------------------------------------------
957 // Handle ioctls. Currently none are defined.
959 static int romfs_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
962 // No Ioctls currenly defined.
967 // -------------------------------------------------------------------------
969 // Force the file out to data storage.
971 static int romfs_fo_fsync (struct CYG_FILE_TAG *fp, int mode )
973 // Data is always permanently where it belongs, nothing to do
979 // -------------------------------------------------------------------------
981 // Close a file. We just clear out the data pointer.
983 static int romfs_fo_close (struct CYG_FILE_TAG *fp)
985 fp->f_data = 0; // zero data pointer
990 // -------------------------------------------------------------------------
994 static int romfs_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf )
996 romfs_node *node = (romfs_node *)fp->f_data;
997 romfs_disk *disk = (romfs_disk*)(fp->f_mte->data);
999 // Fill in the status
1000 buf->st_mode = node->mode;
1001 buf->st_ino = (ino_t)(node - &disk->node[0]);
1002 buf->st_dev = disk->dev_id;
1003 buf->st_nlink = node->nlink;
1004 buf->st_uid = node->uid;
1005 buf->st_gid = node->gid;
1006 buf->st_size = node->size;
1007 buf->st_atime = node->ctime;
1008 buf->st_mtime = node->ctime;
1009 buf->st_ctime = node->ctime;
1014 // -------------------------------------------------------------------------
1015 // romfs_fo_getinfo()
1016 // Get info. Currently only supports fpathconf().
1018 static int romfs_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
1020 romfs_node *node = (romfs_node *)fp->f_data;
1026 err = romfs_pathconf( node, (struct cyg_pathconf_info *)buf );
1035 // -------------------------------------------------------------------------
1036 // romfs_fo_setinfo()
1037 // Set info. Nothing supported here.
1039 static int romfs_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
1041 // No setinfo key supported at present
1047 //==========================================================================
1048 // Directory operations
1050 // -------------------------------------------------------------------------
1051 // romfs_fo_dirread()
1052 // Read a single directory entry from a file.
1054 static int romfs_fo_dirread (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1056 romfs_node *dir = (romfs_node *)fp->f_data;
1057 off_t pos = fp->f_offset;
1059 struct dirent *ent = (struct dirent *)uio->uio_iov[0].iov_base;
1060 char *nbuf = ent->d_name;
1061 int nlen = sizeof(ent->d_name)-1;
1062 off_t len = uio->uio_iov[0].iov_len;
1063 romfs_dirent *d = NULL;
1068 if( len < sizeof(struct dirent) )
1071 // Get the next entry
1072 err = findbuffer_node( (romfs_disk *)fp->f_mte->data, dir, pos, &buf, &size );
1073 if( err != ENOERR || size == 0 || pos >= dir->size )
1076 d = (romfs_dirent *)buf;
1078 for ( i = 0 ; i < nlen && d->name[i] ; i++, nbuf++ )
1080 #ifdef CYGPKG_FS_ROM_RET_DIRENT_DTYPE
1081 ent->d_type = (((romfs_disk *)fp->f_mte->data)->node[d->node]).mode;
1084 // A successful read. Terminate the entry name with a NUL, set the
1085 // residue and set the file offset to restart at the next
1089 uio->uio_resid -= sizeof(struct dirent);
1090 fp->f_offset = d->next;
1095 // -------------------------------------------------------------------------
1096 // romfs_fo_dirlseek()
1097 // Seek directory to start.
1099 static int romfs_fo_dirlseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence )
1101 // Only allow SEEK_SET to zero
1103 if( whence != SEEK_SET || *pos != 0)
1106 *pos = fp->f_offset = 0;
1111 // -------------------------------------------------------------------------