size_t *size, // returned buffer size
cyg_bool alloc) // extend allocation?
{
- if( alloc && (pos == node->datasize || node->datasize == 0) )
+ if( alloc && (pos >= node->datasize || node->datasize == 0) )
{
// If we are allowed to alloc new data, and we are at the end of the
// current data allocation, or there is no data present, allocate or
newdata = realloc( node->data, pos+CYGNUM_RAMFS_REALLOC_INCREMENT );
if( newdata == NULL ) return ENOSPC;
- else memset( newdata+pos, 0, CYGNUM_RAMFS_REALLOC_INCREMENT );
+ else memset( newdata + node->datasize, 0,
+ pos + CYGNUM_RAMFS_REALLOC_INCREMENT - node->datasize );
node->data = newdata;
node->datasize = pos+CYGNUM_RAMFS_REALLOC_INCREMENT;
ramfs_block *b;
*buffer = NULL;
- *size = 0;
+ *size = CYGNUM_RAMFS_BLOCK_SIZE - bpos;
if( bi >= nblocks )
return ENOERR;
if( b == NULL )
{
// There is no block there. If _alloc_ is true we can fill the
- // slot in with a new block. If it is false, we indicate end of
- // data with a zero size result.
+ // slot in with a new block. If it is false, we indicate there
+ // is no block and size indicates where the block would end if
+ // it existed.
if( alloc )
{
b = block_alloc();
}
*buffer = &((*b)[bpos]);
- *size = CYGNUM_RAMFS_BLOCK_SIZE - bpos;
return ENOERR;
}
ramfs_dirent *d;
cyg_uint8 *buf;
size_t size;
-
+
// look for a first name fragment
for(;;)
{
- err = findbuffer_node( dir, pos, &buf, &size, false );
+ err = findbuffer_node( dir, pos, &buf, &size, false );
if( err != ENOERR || size == 0)
return NULL;
if( size < sizeof(ramfs_dirent) || !d->inuse || !d->first )
{
pos += sizeof(ramfs_dirent);
- continue;
+ if ( pos < dir->size )
+ continue;
+ // End if directory, didn't find it.
+ return NULL;
}
break;
fraglen = d->fraglen;
// compare strings, if different, look for another
- if( memcmp( frag, d->name, fraglen ) != 0 )
- break;
-
+ if( memcmp( frag, d->name, fraglen ) != 0 ) {
+ break;
+ }
frag += fraglen;
// If we are at the last fragment, then the whole name string
// has matched and we have a successful search.
- if( d->last )
- return first;
-
+ if( d->last )
+ return first;
+
// Otherwise move on to next entry in chain
err = findbuffer_node( dir, d->next, &buf, &size, false );
if( err != ENOERR )
// Allocate a node to be the root of this filesystem and initialize it.
- root = alloc_node(__stat_mode_DIR);
+ root = alloc_node(__stat_mode_DIR|S_IRWXU|S_IRWXG|S_IRWXO);
if( root == NULL )
return ENOSPC;
// create a new one. The dir and name fields of the dirsearch
// object will have been updated so we know where to put it.
- node = alloc_node( __stat_mode_REG );
+ node = alloc_node( __stat_mode_REG|S_IRWXU|S_IRWXG|S_IRWXO);
if( node == NULL )
return ENOSPC;
// the pathname, so we can create it here.
int doterr, dotdoterr, direrr;
- node = alloc_node( __stat_mode_DIR );
+ node = alloc_node( __stat_mode_DIR | S_IRWXU|S_IRWXG|S_IRWXO);
if( node == NULL )
return ENOSPC;
// -------------------------------------------------------------------------
// ramfs_getinfo()
-// Getinfo. Currently only support pathconf().
+// Getinfo. Currently only support pathconf() and filesystem usage.
static int ramfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
int key, void *buf, int len )
case FS_INFO_CONF:
err = ramfs_pathconf( ds.node, (struct cyg_pathconf_info *)buf );
break;
-
+#if defined(CYGSEM_FILEIO_BLOCK_USAGE) && defined(CYGPKG_FS_RAM_BLOCKS_ARRAY)
+ // When using malloc for storage this does not make much
+ // sense, so only implement this when using pre-allocated
+ // blocks
+ case FS_INFO_BLOCK_USAGE: {
+ struct cyg_fs_block_usage *usage = (struct cyg_fs_block_usage *) buf;
+ ramfs_block *b;
+
+ usage->total_blocks = CYGNUM_FS_RAM_BLOCKS_ARRAY_SIZE;
+ usage->free_blocks = 0;
+ // Iterate over the free list to count its size
+ b = block_free_list;
+ while(b) {
+ usage->free_blocks++;
+ b=*(ramfs_block **)b;
+ }
+ usage->block_size = CYGNUM_RAMFS_BLOCK_SIZE;
+ return ENOERR;
+ }
+#endif
default:
err = EINVAL;
}
// at present.
if( l > bsize )
l = bsize;
-
- // copy data out
- memcpy( buf, fbuf, l );
-
+
+ if (fbuf) {
+ // copy data out
+ memcpy( buf, fbuf, l );
+ } else { // hole, so return zeros here.
+ memset( buf, 0, l );
+ }
+
// Update working vars
len -= l;
buf += l;
if( fp->f_flag & CYG_FAPPEND )
pos = fp->f_offset = node->size;
- // Check that pos is within current file size, or at the very end.
- if( pos < 0 || pos > node->size )
- return EINVAL;
-
// Now loop over the iovecs until they are all done, or
// we get an error.
for( i = 0; i < uio->uio_iovcnt; i++ )
return EINVAL;
}
- // Check that pos is still within current file size, or at the
- // very end.
- if( pos < 0 || pos > node->size )
- return EINVAL;
-
// All OK, set fp offset and return new position.
*apos = fp->f_offset = pos;
memcpy( nbuf, d->name, fraglen);
nbuf += fraglen;
nlen -= fraglen;
+#ifdef CYGPKG_FS_RAM_RET_DIRENT_DTYPE
+ ent->d_type = d->node->mode;
+#endif
// if we hit the last entry, we have a successful transfer
if( d->last || nlen == 0)