Filesystem: PR1398: Fix lseek() mechanic

According to POSIX the lseek() function shall not, by itself, extend the
size of a file.

Remove the size field of rtems_libio_t.  A file has only one size but
may have multiple open file descriptors.  Thus a file size field in the
file descriptor may lead to inconsistencies.

New default handlers rtems_filesystem_default_lseek_file() and
rtems_filesystem_default_lseek_directory().
This commit is contained in:
Sebastian Huber
2012-05-07 16:30:37 +02:00
parent eb7c6a84b6
commit 30d412469c
25 changed files with 198 additions and 426 deletions

View File

@@ -206,7 +206,7 @@ static const rtems_filesystem_file_handlers_r rtems_blkdev_imfs_node = {
.read_h = rtems_blkdev_imfs_read, .read_h = rtems_blkdev_imfs_read,
.write_h = rtems_blkdev_imfs_write, .write_h = rtems_blkdev_imfs_write,
.ioctl_h = rtems_blkdev_imfs_ioctl, .ioctl_h = rtems_blkdev_imfs_ioctl,
.lseek_h = rtems_filesystem_default_lseek_success, .lseek_h = rtems_filesystem_default_lseek_file,
.fstat_h = rtems_blkdev_imfs_fstat, .fstat_h = rtems_blkdev_imfs_fstat,
.ftruncate_h = rtems_filesystem_default_ftruncate, .ftruncate_h = rtems_filesystem_default_ftruncate,
.fsync_h = rtems_blkdev_imfs_fsync_or_fdatasync, .fsync_h = rtems_blkdev_imfs_fsync_or_fdatasync,

View File

@@ -849,8 +849,9 @@ typedef int (*rtems_filesystem_ioctl_t)(
* @retval non-negative The new offset from the beginning of the file. * @retval non-negative The new offset from the beginning of the file.
* @retval -1 An error occured. The errno is set to indicate the error. * @retval -1 An error occured. The errno is set to indicate the error.
* *
* @see rtems_filesystem_default_lseek() and * @see rtems_filesystem_default_lseek(),
* rtems_filesystem_default_lseek_success(). * rtems_filesystem_default_lseek_file(), and
* rtems_filesystem_default_lseek_directory().
*/ */
typedef off_t (*rtems_filesystem_lseek_t)( typedef off_t (*rtems_filesystem_lseek_t)(
rtems_libio_t *iop, rtems_libio_t *iop,
@@ -1025,12 +1026,52 @@ off_t rtems_filesystem_default_lseek(
int whence int whence
); );
/**
* @brief An offset 0 with a whence of SEEK_SET will perform a directory rewind
* operation.
*
* This function has no protection against concurrent access.
*
* @retval -1 The offset is not zero or the whence is not SEEK_SET.
* @retval 0 Successful rewind operation.
*
* @see rtems_filesystem_lseek_t.
*/
off_t rtems_filesystem_default_lseek_directory(
rtems_libio_t *iop,
off_t offset,
int whence
);
/**
* @brief Default lseek() handler for files.
*
* The fstat() handler will be used to obtain the file size in case whence is
* SEEK_END.
*
* This function has no protection against concurrent access.
*
* @retval -1 An error occured. In case an integer overflow occured, then the
* errno will be set to EOVERFLOW. In case the new offset is negative, then
* the errno will be set to EINVAL. In case the whence is SEEK_END and the
* fstat() handler to obtain the current file size returned an error status,
* then the errno will be set by the fstat() handler.
* @retval offset The new offset.
*
* @see rtems_filesystem_lseek_t.
*/
off_t rtems_filesystem_default_lseek_file(
rtems_libio_t *iop,
off_t offset,
int whence
);
/** /**
* @retval 0 Always. * @retval 0 Always.
* *
* @see rtems_filesystem_lseek_t. * @see rtems_filesystem_lseek_t.
*/ */
off_t rtems_filesystem_default_lseek_success( off_t rtems_filesystem_default_lseek_file(
rtems_libio_t *iop, rtems_libio_t *iop,
off_t offset, off_t offset,
int whence int whence
@@ -1157,11 +1198,10 @@ extern const rtems_filesystem_limits_and_options_t
* It will be indexed by 'fd'. * It will be indexed by 'fd'.
* *
* @todo Should really have a separate per/file data structure that this points * @todo Should really have a separate per/file data structure that this points
* to (eg: size, offset, driver, pathname should be in that) * to (eg: offset, driver, pathname should be in that)
*/ */
struct rtems_libio_tt { struct rtems_libio_tt {
rtems_driver_name_t *driver; rtems_driver_name_t *driver;
off_t size; /* size of file */
off_t offset; /* current offset into file */ off_t offset; /* current offset into file */
uint32_t flags; uint32_t flags;
rtems_filesystem_location_info_t pathinfo; rtems_filesystem_location_info_t pathinfo;

View File

@@ -21,65 +21,13 @@
off_t lseek( int fd, off_t offset, int whence ) off_t lseek( int fd, off_t offset, int whence )
{ {
off_t rv = 0;
rtems_libio_t *iop; rtems_libio_t *iop;
off_t reference_offset;
off_t old_offset;
off_t new_offset;
rtems_libio_check_fd( fd ); rtems_libio_check_fd( fd );
iop = rtems_libio_iop( fd ); iop = rtems_libio_iop( fd );
rtems_libio_check_is_open(iop); rtems_libio_check_is_open(iop);
old_offset = iop->offset; return (*iop->pathinfo.handlers->lseek_h)( iop, offset, whence );
switch ( whence ) {
case SEEK_SET:
reference_offset = 0;
break;
case SEEK_CUR:
reference_offset = old_offset;
break;
case SEEK_END:
reference_offset = iop->size;
break;
default:
errno = EINVAL;
rv = (off_t) -1;
break;
}
new_offset = reference_offset + offset;
if ( rv == 0 ) {
if (
(reference_offset >= 0 && new_offset >= offset)
|| (reference_offset < 0 && new_offset <= offset)
) {
switch ( rtems_filesystem_node_type( &iop->pathinfo ) ) {
case RTEMS_FILESYSTEM_DIRECTORY:
case RTEMS_FILESYSTEM_MEMORY_FILE:
if ( new_offset < 0 ) {
errno = EINVAL;
rv = (off_t) -1;
}
break;
default:
break;
}
if ( rv == 0 ) {
iop->offset = new_offset;
rv = (*iop->pathinfo.handlers->lseek_h)( iop, offset, whence );
if ( rv == (off_t) -1 ) {
iop->offset = old_offset;
}
}
} else {
errno = EOVERFLOW;
rv = (off_t) -1;
}
}
return rv;
} }
/* /*

View File

@@ -23,7 +23,8 @@ libdefaultfs_a_SOURCES = \
src/defaults/default_chown.c \ src/defaults/default_chown.c \
src/defaults/default_fcntl.c src/defaults/default_fsmount.c \ src/defaults/default_fcntl.c src/defaults/default_fsmount.c \
src/defaults/default_ftruncate.c src/defaults/default_lseek.c \ src/defaults/default_ftruncate.c src/defaults/default_lseek.c \
src/defaults/default_lseek_success.c \ src/defaults/default_lseek_file.c \
src/defaults/default_lseek_directory.c \
src/defaults/default_readlink.c src/defaults/default_statvfs.c \ src/defaults/default_readlink.c src/defaults/default_statvfs.c \
src/defaults/default_utime.c \ src/defaults/default_utime.c \
src/defaults/default_fstat.c \ src/defaults/default_fstat.c \

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 2012 embedded brains GmbH. All rights reserved. * Copyright (c) 2012 embedded brains GmbH. All rights reserved.
* *
@@ -19,11 +18,20 @@
#include <rtems/libio_.h> #include <rtems/libio_.h>
off_t rtems_filesystem_default_lseek_success( off_t rtems_filesystem_default_lseek_directory(
rtems_libio_t *iop, rtems_libio_t *iop,
off_t offset, off_t offset,
int whence int whence
) )
{ {
return 0; off_t rv = 0;
if ( offset == 0 && whence == SEEK_SET ) {
iop->offset = 0;
} else {
errno = EINVAL;
rv = -1;
}
return rv;
} }

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Obere Lagerstr. 30
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <rtems/libio_.h>
off_t rtems_filesystem_default_lseek_file(
rtems_libio_t *iop,
off_t offset,
int whence
)
{
off_t rv = 0;
off_t reference_offset;
off_t new_offset;
struct stat st;
switch ( whence ) {
case SEEK_SET:
reference_offset = 0;
break;
case SEEK_CUR:
reference_offset = iop->offset;
break;
case SEEK_END:
st.st_size = 0;
rv = (*iop->pathinfo.handlers->fstat_h)( &iop->pathinfo, &st );
reference_offset = st.st_size;
break;
default:
errno = EINVAL;
rv = -1;
break;
}
new_offset = reference_offset + offset;
if ( rv == 0 ) {
if (
(offset >= 0 && new_offset >= reference_offset)
|| (offset < 0 && new_offset < reference_offset)
) {
if ( new_offset >= 0 ) {
iop->offset = new_offset;
rv = new_offset;
} else {
errno = EINVAL;
rv = -1;
}
} else {
errno = EOVERFLOW;
rv = -1;
}
}
return rv;
}

View File

@@ -42,7 +42,7 @@ const rtems_filesystem_file_handlers_r devFS_file_handlers = {
.read_h = devFS_read, .read_h = devFS_read,
.write_h = devFS_write, .write_h = devFS_write,
.ioctl_h = devFS_ioctl, .ioctl_h = devFS_ioctl,
.lseek_h = rtems_filesystem_default_lseek, .lseek_h = rtems_filesystem_default_lseek_file,
.fstat_h = devFS_stat, .fstat_h = devFS_stat,
.ftruncate_h = rtems_filesystem_default_ftruncate, .ftruncate_h = rtems_filesystem_default_ftruncate,
.fsync_h = rtems_filesystem_default_fsync_or_fdatasync, .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,

View File

@@ -286,12 +286,6 @@ ssize_t msdos_file_write(
size_t count /* IN */ size_t count /* IN */
); );
off_t msdos_file_lseek(
rtems_libio_t *iop, /* IN */
off_t offset, /* IN */
int whence /* IN */
);
int msdos_file_stat( int msdos_file_stat(
const rtems_filesystem_location_info_t *loc, const rtems_filesystem_location_info_t *loc,
struct stat *buf struct stat *buf
@@ -322,12 +316,6 @@ ssize_t msdos_dir_read(
size_t count /* IN */ size_t count /* IN */
); );
off_t msdos_dir_lseek(
rtems_libio_t *iop, /* IN */
off_t offset, /* IN */
int whence /* IN */
);
int msdos_dir_sync(rtems_libio_t *iop); int msdos_dir_sync(rtems_libio_t *iop);
int msdos_dir_stat( int msdos_dir_stat(

View File

@@ -465,38 +465,6 @@ msdos_dir_read(rtems_libio_t *iop, void *buffer, size_t count)
* no write for directory * no write for directory
*/ */
/* msdos_dir_lseek --
*
* This routine will behave in one of three ways based on the state of
* argument whence. Based on the state of its value the offset argument will
* be interpreted using one of the following methods:
*
* SEEK_SET - offset is the absolute byte offset from the start of the
* logical start of the dirent sequence that represents the
* directory
* SEEK_CUR - offset is used as the relative byte offset from the current
* directory position index held in the iop structure
* SEEK_END - N/A --> This will cause an assert.
*
* PARAMETERS:
* iop - file control block
* offset - offset
* whence - predefine directive
*
* RETURNS:
* RC_OK on success, or -1 if error occured (errno
* set apropriately).
*/
off_t
msdos_dir_lseek(rtems_libio_t *iop, off_t offset, int whence)
{
if (iop->offset >= 0 && iop->offset <= iop->size) {
return 0;
} else {
rtems_set_errno_and_return_minus_one(EINVAL);
}
}
/* msdos_dir_stat -- /* msdos_dir_stat --
* *
* This routine will obtain the following information concerning the current * This routine will obtain the following information concerning the current

View File

@@ -64,8 +64,6 @@ msdos_file_open(rtems_libio_t *iop, const char *pathname, int oflag,
if (iop->flags & LIBIO_FLAGS_APPEND) if (iop->flags & LIBIO_FLAGS_APPEND)
iop->offset = fat_fd->fat_file_size; iop->offset = fat_fd->fat_file_size;
iop->size = fat_fd->fat_file_size;
rtems_semaphore_release(fs_info->vol_sema); rtems_semaphore_release(fs_info->vol_sema);
return RC_OK; return RC_OK;
} }
@@ -203,60 +201,10 @@ msdos_file_write(rtems_libio_t *iop,const void *buffer, size_t count)
if (iop->offset + ret > fat_fd->fat_file_size) if (iop->offset + ret > fat_fd->fat_file_size)
fat_fd->fat_file_size = iop->offset + ret; fat_fd->fat_file_size = iop->offset + ret;
iop->size = fat_fd->fat_file_size;
rtems_semaphore_release(fs_info->vol_sema); rtems_semaphore_release(fs_info->vol_sema);
return ret; return ret;
} }
/* msdos_file_lseek --
* Process lseek call to the file: extend file if lseek is up to the end
* of the file.
*
* PARAMETERS:
* iop - file control block
* offset - new offset
* whence - predefine directive
*
* RETURNS:
* new offset on success, or -1 if error occured (errno set
* appropriately).
*/
off_t
msdos_file_lseek(rtems_libio_t *iop, off_t offset, int whence)
{
int rc = RC_OK;
rtems_status_code sc = RTEMS_SUCCESSFUL;
msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
uint32_t real_size = 0;
if (iop->offset < 0 || iop->offset > UINT32_MAX) {
rtems_set_errno_and_return_minus_one(EINVAL);
}
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
rtems_set_errno_and_return_minus_one(EIO);
rc = fat_file_extend(iop->pathinfo.mt_entry, fat_fd, iop->offset,
&real_size);
if (rc != RC_OK)
{
rtems_semaphore_release(fs_info->vol_sema);
return rc;
}
if (real_size > fat_fd->fat_file_size)
fat_fd->fat_file_size = iop->offset = real_size;
iop->size = fat_fd->fat_file_size;
rtems_semaphore_release(fs_info->vol_sema);
return iop->offset;
}
/* msdos_file_stat -- /* msdos_file_stat --
* *
* PARAMETERS: * PARAMETERS:
@@ -332,7 +280,7 @@ msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
* file size only if length < fat-file size * file size only if length < fat-file size
*/ */
if (length < fat_fd->fat_file_size) if (length < fat_fd->fat_file_size)
iop->size = fat_fd->fat_file_size = length; fat_fd->fat_file_size = length;
rtems_semaphore_release(fs_info->vol_sema); rtems_semaphore_release(fs_info->vol_sema);
return RC_OK; return RC_OK;

View File

@@ -24,7 +24,7 @@ const rtems_filesystem_file_handlers_r msdos_dir_handlers = {
msdos_dir_read, msdos_dir_read,
rtems_filesystem_default_write, rtems_filesystem_default_write,
rtems_filesystem_default_ioctl, rtems_filesystem_default_ioctl,
msdos_dir_lseek, rtems_filesystem_default_lseek_directory,
msdos_dir_stat, msdos_dir_stat,
rtems_filesystem_default_ftruncate_directory, rtems_filesystem_default_ftruncate_directory,
msdos_dir_sync, msdos_dir_sync,

View File

@@ -24,7 +24,7 @@ const rtems_filesystem_file_handlers_r msdos_file_handlers = {
msdos_file_read, msdos_file_read,
msdos_file_write, msdos_file_write,
rtems_filesystem_default_ioctl, rtems_filesystem_default_ioctl,
msdos_file_lseek, rtems_filesystem_default_lseek_file,
msdos_file_stat, msdos_file_stat,
msdos_file_ftruncate, msdos_file_ftruncate,
msdos_file_sync, msdos_file_sync,

View File

@@ -191,23 +191,6 @@ int device_ioctl(
return args.ioctl_return; return args.ioctl_return;
} }
/*
* device_lseek
*
* This handler eats all lseek() operations and does not create
* an error. It assumes all devices can handle the seek. The
* writes fail.
*/
off_t device_lseek(
rtems_libio_t *iop,
off_t offset,
int whence
)
{
return offset;
}
/* /*
* device_stat * device_stat
* *

View File

@@ -418,12 +418,6 @@ extern ssize_t imfs_dir_read(
size_t count /* IN */ size_t count /* IN */
); );
extern off_t imfs_dir_lseek(
rtems_libio_t *iop, /* IN */
off_t offset, /* IN */
int whence /* IN */
);
extern int memfile_open( extern int memfile_open(
rtems_libio_t *iop, /* IN */ rtems_libio_t *iop, /* IN */
const char *pathname, /* IN */ const char *pathname, /* IN */
@@ -449,12 +443,6 @@ extern int memfile_ioctl(
void *buffer /* IN */ void *buffer /* IN */
); );
extern off_t memfile_lseek(
rtems_libio_t *iop, /* IN */
off_t offset, /* IN */
int whence /* IN */
);
extern int device_open( extern int device_open(
rtems_libio_t *iop, /* IN */ rtems_libio_t *iop, /* IN */
const char *pathname, /* IN */ const char *pathname, /* IN */
@@ -484,12 +472,6 @@ extern int device_ioctl(
void *buffer /* IN */ void *buffer /* IN */
); );
extern off_t device_lseek(
rtems_libio_t *iop, /* IN */
off_t offset, /* IN */
int whence /* IN */
);
extern int device_ftruncate( extern int device_ftruncate(
rtems_libio_t *iop, /* IN */ rtems_libio_t *iop, /* IN */
off_t length /* IN */ off_t length /* IN */

View File

@@ -99,41 +99,3 @@ ssize_t imfs_dir_read(
return bytes_transferred; return bytes_transferred;
} }
/*
* imfs_dir_lseek
*
* This routine will behave in one of three ways based on the state of
* argument whence. Based on the state of its value the offset argument will
* be interpreted using one of the following methods:
*
* SEEK_SET - offset is the absolute byte offset from the start of the
* logical start of the dirent sequence that represents the
* directory
* SEEK_CUR - offset is used as the relative byte offset from the current
* directory position index held in the iop structure
* SEEK_END - N/A --> This will cause an EINVAL to be returned.
*/
off_t imfs_dir_lseek(
rtems_libio_t *iop,
off_t offset,
int whence
)
{
switch( whence ) {
case SEEK_SET: /* absolute move from the start of the file */
case SEEK_CUR: /* relative move */
iop->offset = (iop->offset/sizeof(struct dirent)) *
sizeof(struct dirent);
break;
case SEEK_END: /* Movement past the end of the directory via lseek */
/* is not a permitted operation */
default:
rtems_set_errno_and_return_minus_one( EINVAL );
break;
}
return 0;
}

View File

@@ -36,7 +36,7 @@ static const rtems_filesystem_file_handlers_r IMFS_device_handlers = {
device_read, device_read,
device_write, device_write,
device_ioctl, device_ioctl,
device_lseek, rtems_filesystem_default_lseek_file,
IMFS_stat_device, IMFS_stat_device,
device_ftruncate, device_ftruncate,
rtems_filesystem_default_fsync_or_fdatasync, rtems_filesystem_default_fsync_or_fdatasync,

View File

@@ -52,7 +52,7 @@ static const rtems_filesystem_file_handlers_r IMFS_directory_handlers = {
imfs_dir_read, imfs_dir_read,
rtems_filesystem_default_write, rtems_filesystem_default_write,
rtems_filesystem_default_ioctl, rtems_filesystem_default_ioctl,
imfs_dir_lseek, rtems_filesystem_default_lseek_directory,
IMFS_stat_directory, IMFS_stat_directory,
rtems_filesystem_default_ftruncate_directory, rtems_filesystem_default_ftruncate_directory,
rtems_filesystem_default_fsync_or_fdatasync_success, rtems_filesystem_default_fsync_or_fdatasync_success,

View File

@@ -36,7 +36,7 @@ static const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = {
memfile_read, memfile_read,
memfile_write, memfile_write,
memfile_ioctl, memfile_ioctl,
memfile_lseek, rtems_filesystem_default_lseek_file,
IMFS_stat_file, IMFS_stat_file,
memfile_ftruncate, memfile_ftruncate,
rtems_filesystem_default_fsync_or_fdatasync_success, rtems_filesystem_default_fsync_or_fdatasync_success,

View File

@@ -109,7 +109,6 @@ int memfile_open(
if (iop->flags & LIBIO_FLAGS_APPEND) if (iop->flags & LIBIO_FLAGS_APPEND)
iop->offset = the_jnode->info.file.size; iop->offset = the_jnode->info.file.size;
iop->size = the_jnode->info.file.size;
return 0; return 0;
} }
@@ -148,7 +147,6 @@ ssize_t memfile_write(
the_jnode = iop->pathinfo.node_access; the_jnode = iop->pathinfo.node_access;
status = IMFS_memfile_write( the_jnode, iop->offset, buffer, count ); status = IMFS_memfile_write( the_jnode, iop->offset, buffer, count );
iop->size = the_jnode->info.file.size;
return status; return status;
} }
@@ -169,34 +167,6 @@ int memfile_ioctl(
return 0; return 0;
} }
/*
* memfile_lseek
*
* This routine processes the lseek() system call.
*/
off_t memfile_lseek(
rtems_libio_t *iop,
off_t offset,
int whence
)
{
IMFS_jnode_t *the_jnode;
the_jnode = iop->pathinfo.node_access;
if (IMFS_type( the_jnode ) == IMFS_LINEAR_FILE) {
if (iop->offset > the_jnode->info.linearfile.size)
iop->offset = the_jnode->info.linearfile.size;
}
else { /* Must be a block file (IMFS_MEMORY_FILE). */
if (IMFS_memfile_extend( the_jnode, iop->offset ))
rtems_set_errno_and_return_minus_one( ENOSPC );
iop->size = the_jnode->info.file.size;
}
return iop->offset;
}
/* /*
* memfile_stat * memfile_stat
* *
@@ -232,7 +202,6 @@ int memfile_ftruncate(
* future use and just set the length. * future use and just set the length.
*/ */
the_jnode->info.file.size = length; the_jnode->info.file.size = length;
iop->size = the_jnode->info.file.size;
IMFS_update_atime( the_jnode ); IMFS_update_atime( the_jnode );
@@ -265,7 +234,7 @@ MEMFILE_STATIC int IMFS_memfile_extend(
* Verify new file size is supported * Verify new file size is supported
*/ */
if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE ) if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
rtems_set_errno_and_return_minus_one( EINVAL ); rtems_set_errno_and_return_minus_one( EFBIG );
/* /*
* Verify new file size is actually larger than current size * Verify new file size is actually larger than current size
@@ -654,7 +623,7 @@ MEMFILE_STATIC ssize_t IMFS_memfile_write(
if ( last_byte > the_jnode->info.file.size ) { if ( last_byte > the_jnode->info.file.size ) {
status = IMFS_memfile_extend( the_jnode, last_byte ); status = IMFS_memfile_extend( the_jnode, last_byte );
if ( status ) if ( status )
rtems_set_errno_and_return_minus_one( ENOSPC ); return status;
} }
copied = 0; copied = 0;

View File

@@ -2424,63 +2424,25 @@ int e;
return count; return count;
} }
static off_t nfs_file_lseek(
rtems_libio_t *iop,
off_t length,
int whence
)
{
#if DEBUG & DEBUG_SYSCALLS
fprintf(stderr,
"lseek to %i (length %i, whence %i)\n",
iop->offset,
length,
whence);
#endif
if ( SEEK_END == whence ) {
/* rtems (4.6.2) libcsupport code 'lseek' uses iop->size to
* compute the offset. We don't want to track the file size
* by updating 'iop->size' constantly.
* Since lseek is the only place using iop->size, we work
* around this by tweaking the offset here...
*/
NfsNode node = iop->pathinfo.node_access;
fattr *fa = &SERP_ATTR(node);
if (updateAttr(node, 0 /* only if old */)) {
return -1;
}
iop->offset = fa->size;
}
/* this is particularly easy :-) */
return iop->offset;
}
static off_t nfs_dir_lseek( static off_t nfs_dir_lseek(
rtems_libio_t *iop, rtems_libio_t *iop,
off_t length, off_t length,
int whence int whence
) )
{ {
off_t rv = rtems_filesystem_default_lseek_directory(iop, length, whence);
if (rv == 0) {
DirInfo di = iop->pathinfo.node_access_2; DirInfo di = iop->pathinfo.node_access_2;
nfscookie *cookie = &di->readdirargs.cookie;
/* we don't support anything other than
* rewinding
*/
if (SEEK_SET != whence || 0 != length) {
errno = ENOTSUP;
return -1;
}
/* rewind cookie */
memset( &di->readdirargs.cookie,
0,
sizeof(di->readdirargs.cookie) );
di->eofreached = FALSE; di->eofreached = FALSE;
return iop->offset; /* rewind cookie */
memset(cookie, 0, sizeof(*cookie));
}
return rv;
} }
#if 0 /* structure types for reference */ #if 0 /* structure types for reference */
@@ -2703,7 +2665,7 @@ struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers = {
.read_h = nfs_file_read, .read_h = nfs_file_read,
.write_h = nfs_file_write, .write_h = nfs_file_write,
.ioctl_h = rtems_filesystem_default_ioctl, .ioctl_h = rtems_filesystem_default_ioctl,
.lseek_h = nfs_file_lseek, .lseek_h = rtems_filesystem_default_lseek_file,
.fstat_h = nfs_fstat, .fstat_h = nfs_fstat,
.ftruncate_h = nfs_file_ftruncate, .ftruncate_h = nfs_file_ftruncate,
.fsync_h = rtems_filesystem_default_fsync_or_fdatasync, .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,

View File

@@ -213,24 +213,6 @@ rtems_rfs_rtems_device_ioctl (rtems_libio_t* iop,
return args.ioctl_return; return args.ioctl_return;
} }
/**
* This handler eats all lseek() operations and does not create an error. It
* assumes all devices can handle the seek. The writes fail.
*
* @param iop
* @param offset
* @param whence
* @return off_t
*/
static off_t
rtems_rfs_rtems_device_lseek (rtems_libio_t* iop,
off_t offset,
int whence)
{
return offset;
}
/** /**
* The consumes the truncate call. You cannot truncate device files. * The consumes the truncate call. You cannot truncate device files.
* *
@@ -255,7 +237,7 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_device_handlers = {
.read_h = rtems_rfs_rtems_device_read, .read_h = rtems_rfs_rtems_device_read,
.write_h = rtems_rfs_rtems_device_write, .write_h = rtems_rfs_rtems_device_write,
.ioctl_h = rtems_rfs_rtems_device_ioctl, .ioctl_h = rtems_rfs_rtems_device_ioctl,
.lseek_h = rtems_rfs_rtems_device_lseek, .lseek_h = rtems_filesystem_default_lseek_file,
.fstat_h = rtems_rfs_rtems_fstat, .fstat_h = rtems_rfs_rtems_fstat,
.ftruncate_h = rtems_rfs_rtems_device_ftruncate, .ftruncate_h = rtems_rfs_rtems_device_ftruncate,
.fsync_h = rtems_filesystem_default_fsync_or_fdatasync, .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,

View File

@@ -150,43 +150,6 @@ rtems_rfs_rtems_dir_read (rtems_libio_t* iop,
return bytes_transferred; return bytes_transferred;
} }
/**
* This routine will behave in one of three ways based on the state of argument
* whence. Based on the state of its value the offset argument will be
* interpreted using one of the following methods:
*
* SEEK_SET - offset is the absolute byte offset from the start of the
* logical start of the dirent sequence that represents the
* directory
* SEEK_CUR - offset is used as the relative byte offset from the current
* directory position index held in the iop structure
* SEEK_END - N/A --> This will cause an assert.
*
* @param iop
* @param offset
* @param whence
* return off_t
*/
static off_t
rtems_rfs_rtems_dir_lseek (rtems_libio_t* iop,
off_t offset,
int whence)
{
switch (whence)
{
case SEEK_SET: /* absolute move from the start of the file */
case SEEK_CUR: /* relative move */
break;
case SEEK_END: /* Movement past the end of the directory via lseek */
/* is not a permitted operation */
default:
return rtems_rfs_rtems_error ("dir_lseek: bad whence", EINVAL);
break;
}
return 0;
}
/* /*
* Set of operations handlers for operations on directories. * Set of operations handlers for operations on directories.
*/ */
@@ -197,7 +160,7 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_dir_handlers = {
.read_h = rtems_rfs_rtems_dir_read, .read_h = rtems_rfs_rtems_dir_read,
.write_h = rtems_filesystem_default_write, .write_h = rtems_filesystem_default_write,
.ioctl_h = rtems_filesystem_default_ioctl, .ioctl_h = rtems_filesystem_default_ioctl,
.lseek_h = rtems_rfs_rtems_dir_lseek, .lseek_h = rtems_filesystem_default_lseek_directory,
.fstat_h = rtems_rfs_rtems_fstat, .fstat_h = rtems_rfs_rtems_fstat,
.ftruncate_h = rtems_filesystem_default_ftruncate_directory, .ftruncate_h = rtems_filesystem_default_ftruncate_directory,
.fsync_h = rtems_filesystem_default_fsync_or_fdatasync, .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,

View File

@@ -72,7 +72,6 @@ rtems_rfs_rtems_file_open (rtems_libio_t* iop,
if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN)) if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN))
printf("rtems-rfs: file-open: handle:%p\n", file); printf("rtems-rfs: file-open: handle:%p\n", file);
iop->size = rtems_rfs_file_size (file);
rtems_rfs_rtems_set_iop_file_handle (iop, file); rtems_rfs_rtems_set_iop_file_handle (iop, file);
rtems_rfs_rtems_unlock (fs); rtems_rfs_rtems_unlock (fs);
@@ -245,8 +244,6 @@ rtems_rfs_rtems_file_write (rtems_libio_t* iop,
} }
} }
iop->size = rtems_rfs_file_size (file);
rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
return write; return write;
@@ -282,26 +279,32 @@ rtems_rfs_rtems_file_lseek (rtems_libio_t* iop,
int whence) int whence)
{ {
rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop); rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
rtems_rfs_pos pos; off_t old_offset;
int rc; off_t new_offset;
if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_LSEEK)) if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_LSEEK))
printf("rtems-rfs: file-lseek: handle:%p offset:%" PRIdoff_t "\n", file, offset); printf("rtems-rfs: file-lseek: handle:%p offset:%" PRIdoff_t "\n", file, offset);
rtems_rfs_rtems_lock (rtems_rfs_file_fs (file)); rtems_rfs_rtems_lock (rtems_rfs_file_fs (file));
pos = iop->offset; old_offset = iop->offset;
new_offset = rtems_filesystem_default_lseek_file (iop, offset, whence);
if (new_offset != -1)
{
rtems_rfs_pos pos = iop->offset;
int rc = rtems_rfs_file_seek (file, pos, &pos);
rc = rtems_rfs_file_seek (file, pos, &pos);
if (rc) if (rc)
{ {
rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); rtems_rfs_rtems_error ("file_lseek: lseek", rc);
return rtems_rfs_rtems_error ("file_lseek: lseek", rc); iop->offset = old_offset;
new_offset = -1;
}
} }
rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
return iop->offset; return new_offset;
} }
/** /**
@@ -327,8 +330,6 @@ rtems_rfs_rtems_file_ftruncate (rtems_libio_t* iop,
if (rc) if (rc)
rc = rtems_rfs_rtems_error ("file_ftruncate: set size", rc); rc = rtems_rfs_rtems_error ("file_ftruncate: set size", rc);
iop->size = rtems_rfs_file_size (file);
rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
return rc; return rc;

View File

@@ -371,7 +371,7 @@ lseek_test (void)
*/ */
status = fstat (fd, &statbuf); status = fstat (fd, &statbuf);
rtems_test_assert (status == 0); rtems_test_assert (status == 0);
rtems_test_assert (statbuf.st_size == total_written + 1); rtems_test_assert (statbuf.st_size == total_written);
status = ftruncate (fd, total_written); status = ftruncate (fd, total_written);
rtems_test_assert (status == 0); rtems_test_assert (status == 0);

View File

@@ -56,7 +56,7 @@ void write_helper(void)
do { do {
written = write( TestFd, Buffer, sizeof(Buffer) ); written = write( TestFd, Buffer, sizeof(Buffer) );
if ( written == -1 ) { if ( written == -1 ) {
if ( errno == ENOSPC ) { if ( errno == EFBIG ) {
printf( "Total written = %zd\n", TotalWritten ); printf( "Total written = %zd\n", TotalWritten );
return; return;
} }
@@ -93,13 +93,7 @@ void read_helper(void)
rtems_test_exit(0); rtems_test_exit(0);
} }
i++; i++;
continue; } else if ( sc != 0 ) {
}
/* Unsure if ENOSPC is the write error to be returned */
if ( errno == ENOSPC && i == TotalWritten ) {
puts( "File correctly read until ENOSPC returned\n" );
return;
}
fprintf( fprintf(
stderr, stderr,
"ERROR - at offset %d - returned %zd and error=%s\n", "ERROR - at offset %d - returned %zd and error=%s\n",
@@ -108,7 +102,12 @@ void read_helper(void)
strerror( errno ) strerror( errno )
); );
rtems_test_exit(0); rtems_test_exit(0);
} while (1); }
} while ( sc > 0 );
if ( i == TotalWritten ) {
puts( "File correctly read until EOF returned\n" );
}
} }
void truncate_helper(void) void truncate_helper(void)
@@ -143,7 +142,7 @@ void truncate_helper(void)
} while (new > 0); } while (new > 0);
} }
void extend_helper(void) void extend_helper(int eno)
{ {
off_t position; off_t position;
off_t new; off_t new;
@@ -164,18 +163,11 @@ void extend_helper(void)
new = position; new = position;
do { do {
sc = lseek( TestFd, new, SEEK_SET ); sc = lseek( TestFd, new, SEEK_SET );
if( sc == -1 ) { rtems_test_assert( sc == new );
if( errno == ENOSPC ) {
break;
}
else {
rtems_test_assert( 0 );
}
}
rc = ftruncate( TestFd, new ); rc = ftruncate( TestFd, new );
if ( rc != 0 ) { if ( rc != 0 ) {
if( errno != ENOSPC ) { if( errno != eno ) {
fprintf( fprintf(
stderr, stderr,
"ERROR - at offset %d - returned %d and error=%s\n", "ERROR - at offset %d - returned %d and error=%s\n",
@@ -218,8 +210,10 @@ rtems_task Init(
{ {
int i; int i;
void *alloc_ptr = (void *)0; void *alloc_ptr = (void *)0;
int position = 0; off_t position;
int status = 0; off_t new_position;
char buf [1];
ssize_t n;
puts( "\n\n*** TEST IMFS 01 ***" ); puts( "\n\n*** TEST IMFS 01 ***" );
@@ -244,18 +238,21 @@ rtems_task Init(
*/ */
alloc_ptr = malloc( malloc_free_space() - 4 ); alloc_ptr = malloc( malloc_free_space() - 4 );
extend_helper(); extend_helper(ENOSPC);
/* /*
* free the allocated heap memory * free the allocated heap memory
*/ */
free(alloc_ptr); free(alloc_ptr);
extend_helper(); extend_helper(EFBIG);
position = lseek( TestFd , 0, SEEK_END ); position = lseek( TestFd , 0, SEEK_END );
status = lseek( TestFd, position+2, SEEK_SET ); new_position = lseek( TestFd, position + 2, SEEK_SET );
rtems_test_assert( status == -1 ); rtems_test_assert( new_position == position + 2 );
rtems_test_assert( errno == ENOSPC );
n = write( TestFd, buf, sizeof(buf) );
rtems_test_assert( n == -1 );
rtems_test_assert( errno == EFBIG );
close_it(); close_it();
unlink_it(); unlink_it();