]> git.kernelconcepts.de Git - karo-tx-redboot.git/blobdiff - packages/fs/ram/v2_0/src/ramfs.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / fs / ram / v2_0 / src / ramfs.c
index b1d456f747c7e68ea5e62a6289a9a02fbfe67f2c..1bf4759d3f0fd6df7718daae4ea0cd758f6c6b29 100644 (file)
@@ -654,7 +654,7 @@ static int findbuffer_node( ramfs_node  *node,  // node pointer
                             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
@@ -668,7 +668,8 @@ static int findbuffer_node( ramfs_node  *node,  // node pointer
             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;
@@ -730,7 +731,7 @@ static int findbuffer_direct( off_t pos,
     ramfs_block *b;
     
     *buffer = NULL;
-    *size = 0;
+    *size = CYGNUM_RAMFS_BLOCK_SIZE - bpos;
     
     if( bi >= nblocks )
         return ENOERR;
@@ -740,8 +741,9 @@ static int findbuffer_direct( off_t pos,
     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();
@@ -753,7 +755,6 @@ static int findbuffer_direct( off_t pos,
     }
 
     *buffer = &((*b)[bpos]);
-    *size = CYGNUM_RAMFS_BLOCK_SIZE - bpos;
 
     return ENOERR;
 }
@@ -1209,11 +1210,11 @@ static ramfs_dirent *find_direntry( ramfs_node *dir, const char *name, int namel
         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;
 
@@ -1222,7 +1223,10 @@ static ramfs_dirent *find_direntry( ramfs_node *dir, const char *name, int namel
             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;
@@ -1247,17 +1251,17 @@ static ramfs_dirent *find_direntry( ramfs_node *dir, const char *name, int namel
                     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 )
@@ -1491,7 +1495,7 @@ static int ramfs_mount    ( cyg_fstab_entry *fste, cyg_mtab_entry *mte )
     
     // 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;
@@ -1565,7 +1569,7 @@ static int ramfs_open     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
             // 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;
@@ -1669,7 +1673,7 @@ static int ramfs_mkdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
             // 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;
@@ -1976,7 +1980,7 @@ static int ramfs_stat     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
 
 // -------------------------------------------------------------------------
 // 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 )
@@ -1995,7 +1999,26 @@ static int ramfs_getinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
     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;
     }
@@ -2058,10 +2081,14 @@ static int ramfs_fo_read      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
             // 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;
@@ -2098,10 +2125,6 @@ static int ramfs_fo_write     (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
     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++ )
@@ -2186,11 +2209,6 @@ static int ramfs_fo_lseek     (struct CYG_FILE_TAG *fp, off_t *apos, int whence
         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;
     
@@ -2352,6 +2370,9 @@ static int ramfs_fo_dirread      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *u
         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)