This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
RAMFS fixes: file permissions and lseek()
- From: Dan Jakubiec <dan dot jakubiec at systech dot com>
- To: eCos Patch List <ecos-patches at sources dot redhat dot com>
- Date: Thu, 29 Sep 2005 14:50:47 -1000
- Subject: RAMFS fixes: file permissions and lseek()
Attached for your review is a patch for the RAMFS filesystem which
addresses the following items:
2005-05-29 Dan Jakubiec <dan.jakubiec@systech.com>
* src/ramfs.c:
(ramfs_mount, ramfs_open, ramfs_mkdir) Changed the permissions
for files
and directories created on RAMFS filesystems from 000 to 777.
This helps
applications which check for the existence of certain file
permissions.
(ramfs_fo_write, ramfs_fo_lseek) Fixed the RAMFS implementation
of lseek()
to make it POSIX-compliant. The previous implementation did not
handle
lseek()'s beyond the EOF.
The POSIX documentation for lseek() says:
The /lseek/() function shall allow the file offset to be set beyond
the end of the existing data in the file. If data is later written
at this point, subsequent reads of data in the gap shall return
bytes with the value 0 until data is actually written into the gap.
The /lseek/() function shall not, by itself, extend the size of a file.
Thanks,
--
Dan Jakubiec
Systech Corporation
Index: ecos/packages/fs/ram/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/ram/current/ChangeLog,v
retrieving revision 1.15
diff -u -5 -p -r1.15 ChangeLog
--- ecos/packages/fs/ram/current/ChangeLog 27 Mar 2005 18:21:15 -0000 1.15
+++ ecos/packages/fs/ram/current/ChangeLog 30 Sep 2005 00:29:30 -0000
@@ -1,5 +1,16 @@
+2005-05-29 Dan Jakubiec <dan.jakubiec@systech.com>
+
+ * src/ramfs.c:
+ (ramfs_mount, ramfs_open, ramfs_mkdir) Changed the permissions for files
+ and directories created on RAMFS filesystems from 000 to 777. This helps
+ applications which check for the existence of certain file permissions.
+
+ (ramfs_fo_write, ramfs_fo_lseek) Fixed the RAMFS implementation of lseek()
+ to make it POSIX-compliant. The previous implementation did not handle
+ lseek()'s beyond the EOF.
+
2005-03-27 Andrew Lunn <andrew.lunn@ascom.ch>
* tests/ramfs1.c (SHOW_RESULT): Fixed compiler warning about format
not matching type.
Index: ecos/packages/fs/ram/current/src/ramfs.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/ram/current/src/ramfs.c,v
retrieving revision 1.8
diff -u -5 -p -r1.8 ramfs.c
--- ecos/packages/fs/ram/current/src/ramfs.c 15 Mar 2004 17:17:10 -0000 1.8
+++ ecos/packages/fs/ram/current/src/ramfs.c 30 Sep 2005 00:29:32 -0000
@@ -1489,11 +1489,11 @@ static int ramfs_mount ( cyg_fstab_en
ramfs_node *root;
int err;
// 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;
// Add . and .. entries back to self.
@@ -1563,11 +1563,11 @@ static int ramfs_open ( cyg_mtab_ent
{
// No node there, if the O_CREAT bit is set then we must
// 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;
err = add_direntry( ds.dir, ds.name, ds.namelen, node );
@@ -1667,11 +1667,11 @@ static int ramfs_mkdir ( cyg_mtab_ent
{
// The entry does not exist, and it is the last element in
// 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;
// Add "." and ".." entries.
@@ -2096,52 +2096,82 @@ static int ramfs_fo_write (struct CY
// If the APPEND mode bit was supplied, force all writes to
// the end of the file.
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 )
+ // Check that pos is valid.
+ if( (pos < 0) || (pos > RAMFS_FILESIZE_MAX) )
return EINVAL;
+ // If the current file position has been set beyond the end of the file,
+ // then we must now zero-fill the unwritten area before adding new data.
+ while( pos > node->size )
+ {
+ cyg_uint8 *fbuf;
+ size_t bsize;
+ off_t num_zero = pos - node->size;
+
+ // Get the next chunk of buffer space
+ err = findbuffer_node( node, node->size, &fbuf, &bsize, true );
+
+ // Stop writing if there is no more space in the file.
+ if( err == ENOSPC )
+ {
+ pos = node->size;
+ break;
+ }
+ if( err != ENOERR )
+ return err;
+
+ // Zero-fill as many bytes as possible/necessary in the current block.
+ if( num_zero > bsize )
+ num_zero = bsize;
+ memset( fbuf, 0, num_zero );
+ node->size += num_zero;
+ }
+
// Now loop over the iovecs until they are all done, or
// we get an error.
- for( i = 0; i < uio->uio_iovcnt; i++ )
+ if ( err == ENOERR)
{
- cyg_iovec *iov = &uio->uio_iov[i];
- char *buf = (char *)iov->iov_base;
- off_t len = iov->iov_len;
-
- // loop over the vector writing it to the file until it has
- // all been done.
- while( len > 0 )
+ for( i = 0; i < uio->uio_iovcnt; i++ )
{
- cyg_uint8 *fbuf;
- size_t bsize;
- off_t l = len;
-
- err = findbuffer_node( node, pos, &fbuf, &bsize, true );
-
- // Stop writing if there is no more space in the file and
- // indicate end of data.
- if( err == ENOSPC )
- break;
-
- if( err != ENOERR )
- return err;
-
- // adjust size to this block
- if( l > bsize )
- l = bsize;
-
- // copy data in
- memcpy( fbuf, buf, l );
+ cyg_iovec *iov = &uio->uio_iov[i];
+ char *buf = (char *)iov->iov_base;
+ off_t len = iov->iov_len;
+
+ // loop over the vector writing it to the file until it has
+ // all been done.
+ while( len > 0 )
+ {
+ cyg_uint8 *fbuf;
+ size_t bsize;
+ off_t l = len;
+
+ err = findbuffer_node( node, pos, &fbuf, &bsize, true );
- // Update working vars
- len -= l;
- buf += l;
- pos += l;
- resid -= l;
+ // Stop writing if there is no more space in the file and
+ // indicate end of data.
+ if( err == ENOSPC )
+ break;
+
+ if( err != ENOERR )
+ return err;
+
+ // adjust size to this block
+ if( l > bsize )
+ l = bsize;
+
+ // copy data in
+ memcpy( fbuf, buf, l );
+
+ // Update working vars
+ len -= l;
+ buf += l;
+ pos += l;
+ resid -= l;
+ }
}
}
// We wrote some data successfully, update the modified and access
// times of the node, increase its size appropriately, and update
@@ -2150,11 +2180,12 @@ static int ramfs_fo_write (struct CY
node->ctime = cyg_timestamp();
if( pos > node->size )
node->size = pos;
uio->uio_resid = resid;
- fp->f_offset = pos;
+ if( fp->f_offset < pos )
+ fp->f_offset = pos;
return err;
}
// -------------------------------------------------------------------------
@@ -2184,13 +2215,12 @@ static int ramfs_fo_lseek (struct CY
default:
return EINVAL;
}
- // Check that pos is still within current file size, or at the
- // very end.
- if( pos < 0 || pos > node->size )
+ // Check that pos is valid. It's okay for it go beyond the end of file.
+ if( (pos < 0) || (pos > RAMFS_FILESIZE_MAX) )
return EINVAL;
// All OK, set fp offset and return new position.
*apos = fp->f_offset = pos;