From 30d412469c930fe4150ad2b9a321eea2747ec6f4 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 7 May 2012 16:30:37 +0200 Subject: 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(). --- cpukit/libblock/src/blkdev-imfs.c | 2 +- cpukit/libcsupport/include/rtems/libio.h | 50 ++++++++++++++-- cpukit/libcsupport/src/lseek.c | 54 +---------------- cpukit/libfs/Makefile.am | 3 +- .../libfs/src/defaults/default_lseek_directory.c | 37 ++++++++++++ cpukit/libfs/src/defaults/default_lseek_file.c | 70 ++++++++++++++++++++++ cpukit/libfs/src/defaults/default_lseek_success.c | 29 --------- cpukit/libfs/src/devfs/devfs_init.c | 2 +- cpukit/libfs/src/dosfs/msdos.h | 12 ---- cpukit/libfs/src/dosfs/msdos_dir.c | 32 ---------- cpukit/libfs/src/dosfs/msdos_file.c | 54 +---------------- cpukit/libfs/src/dosfs/msdos_handlers_dir.c | 2 +- cpukit/libfs/src/dosfs/msdos_handlers_file.c | 2 +- cpukit/libfs/src/imfs/deviceio.c | 17 ------ cpukit/libfs/src/imfs/imfs.h | 18 ------ cpukit/libfs/src/imfs/imfs_directory.c | 38 ------------ cpukit/libfs/src/imfs/imfs_handlers_device.c | 2 +- cpukit/libfs/src/imfs/imfs_handlers_directory.c | 2 +- cpukit/libfs/src/imfs/imfs_handlers_memfile.c | 2 +- cpukit/libfs/src/imfs/memfile.c | 35 +---------- cpukit/libfs/src/nfsclient/src/nfs.c | 58 ++++-------------- cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c | 20 +------ cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c | 39 +----------- cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c | 29 ++++----- testsuites/fstests/fsrdwr/init.c | 2 +- testsuites/psxtests/psximfs01/init.c | 63 ++++++++++--------- 26 files changed, 223 insertions(+), 451 deletions(-) create mode 100644 cpukit/libfs/src/defaults/default_lseek_directory.c create mode 100644 cpukit/libfs/src/defaults/default_lseek_file.c delete mode 100644 cpukit/libfs/src/defaults/default_lseek_success.c diff --git a/cpukit/libblock/src/blkdev-imfs.c b/cpukit/libblock/src/blkdev-imfs.c index fe7a80cc2c..86455930f6 100644 --- a/cpukit/libblock/src/blkdev-imfs.c +++ b/cpukit/libblock/src/blkdev-imfs.c @@ -206,7 +206,7 @@ static const rtems_filesystem_file_handlers_r rtems_blkdev_imfs_node = { .read_h = rtems_blkdev_imfs_read, .write_h = rtems_blkdev_imfs_write, .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, .ftruncate_h = rtems_filesystem_default_ftruncate, .fsync_h = rtems_blkdev_imfs_fsync_or_fdatasync, diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h index 04ca52c4aa..a740a408f0 100644 --- a/cpukit/libcsupport/include/rtems/libio.h +++ b/cpukit/libcsupport/include/rtems/libio.h @@ -849,8 +849,9 @@ typedef int (*rtems_filesystem_ioctl_t)( * @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. * - * @see rtems_filesystem_default_lseek() and - * rtems_filesystem_default_lseek_success(). + * @see rtems_filesystem_default_lseek(), + * rtems_filesystem_default_lseek_file(), and + * rtems_filesystem_default_lseek_directory(). */ typedef off_t (*rtems_filesystem_lseek_t)( rtems_libio_t *iop, @@ -1025,12 +1026,52 @@ off_t rtems_filesystem_default_lseek( 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. * * @see rtems_filesystem_lseek_t. */ -off_t rtems_filesystem_default_lseek_success( +off_t rtems_filesystem_default_lseek_file( rtems_libio_t *iop, off_t offset, int whence @@ -1157,11 +1198,10 @@ extern const rtems_filesystem_limits_and_options_t * It will be indexed by 'fd'. * * @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 { rtems_driver_name_t *driver; - off_t size; /* size of file */ off_t offset; /* current offset into file */ uint32_t flags; rtems_filesystem_location_info_t pathinfo; diff --git a/cpukit/libcsupport/src/lseek.c b/cpukit/libcsupport/src/lseek.c index 7c1f76b36b..fa18db33f4 100644 --- a/cpukit/libcsupport/src/lseek.c +++ b/cpukit/libcsupport/src/lseek.c @@ -21,65 +21,13 @@ off_t lseek( int fd, off_t offset, int whence ) { - off_t rv = 0; rtems_libio_t *iop; - off_t reference_offset; - off_t old_offset; - off_t new_offset; rtems_libio_check_fd( fd ); iop = rtems_libio_iop( fd ); rtems_libio_check_is_open(iop); - old_offset = iop->offset; - 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; + return (*iop->pathinfo.handlers->lseek_h)( iop, offset, whence ); } /* diff --git a/cpukit/libfs/Makefile.am b/cpukit/libfs/Makefile.am index c629bc99a1..f236704bdd 100644 --- a/cpukit/libfs/Makefile.am +++ b/cpukit/libfs/Makefile.am @@ -23,7 +23,8 @@ libdefaultfs_a_SOURCES = \ src/defaults/default_chown.c \ src/defaults/default_fcntl.c src/defaults/default_fsmount.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_utime.c \ src/defaults/default_fstat.c \ diff --git a/cpukit/libfs/src/defaults/default_lseek_directory.c b/cpukit/libfs/src/defaults/default_lseek_directory.c new file mode 100644 index 0000000000..e50eefd667 --- /dev/null +++ b/cpukit/libfs/src/defaults/default_lseek_directory.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * 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 + +off_t rtems_filesystem_default_lseek_directory( + rtems_libio_t *iop, + off_t offset, + int whence +) +{ + off_t rv = 0; + + if ( offset == 0 && whence == SEEK_SET ) { + iop->offset = 0; + } else { + errno = EINVAL; + rv = -1; + } + + return rv; +} diff --git a/cpukit/libfs/src/defaults/default_lseek_file.c b/cpukit/libfs/src/defaults/default_lseek_file.c new file mode 100644 index 0000000000..9d80b2a176 --- /dev/null +++ b/cpukit/libfs/src/defaults/default_lseek_file.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * 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 + +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; +} diff --git a/cpukit/libfs/src/defaults/default_lseek_success.c b/cpukit/libfs/src/defaults/default_lseek_success.c deleted file mode 100644 index d6a1cb4d8c..0000000000 --- a/cpukit/libfs/src/defaults/default_lseek_success.c +++ /dev/null @@ -1,29 +0,0 @@ - -/* - * Copyright (c) 2012 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * 82178 Puchheim - * Germany - * - * - * 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 - -off_t rtems_filesystem_default_lseek_success( - rtems_libio_t *iop, - off_t offset, - int whence -) -{ - return 0; -} diff --git a/cpukit/libfs/src/devfs/devfs_init.c b/cpukit/libfs/src/devfs/devfs_init.c index db856d21fa..154f1b9176 100644 --- a/cpukit/libfs/src/devfs/devfs_init.c +++ b/cpukit/libfs/src/devfs/devfs_init.c @@ -42,7 +42,7 @@ const rtems_filesystem_file_handlers_r devFS_file_handlers = { .read_h = devFS_read, .write_h = devFS_write, .ioctl_h = devFS_ioctl, - .lseek_h = rtems_filesystem_default_lseek, + .lseek_h = rtems_filesystem_default_lseek_file, .fstat_h = devFS_stat, .ftruncate_h = rtems_filesystem_default_ftruncate, .fsync_h = rtems_filesystem_default_fsync_or_fdatasync, diff --git a/cpukit/libfs/src/dosfs/msdos.h b/cpukit/libfs/src/dosfs/msdos.h index 9bdfd881ec..a7aff1d96d 100644 --- a/cpukit/libfs/src/dosfs/msdos.h +++ b/cpukit/libfs/src/dosfs/msdos.h @@ -286,12 +286,6 @@ ssize_t msdos_file_write( 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( const rtems_filesystem_location_info_t *loc, struct stat *buf @@ -322,12 +316,6 @@ ssize_t msdos_dir_read( 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_stat( diff --git a/cpukit/libfs/src/dosfs/msdos_dir.c b/cpukit/libfs/src/dosfs/msdos_dir.c index 67a0bdaaa9..be6b5a91ff 100644 --- a/cpukit/libfs/src/dosfs/msdos_dir.c +++ b/cpukit/libfs/src/dosfs/msdos_dir.c @@ -465,38 +465,6 @@ msdos_dir_read(rtems_libio_t *iop, void *buffer, size_t count) * 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 -- * * This routine will obtain the following information concerning the current diff --git a/cpukit/libfs/src/dosfs/msdos_file.c b/cpukit/libfs/src/dosfs/msdos_file.c index 7cd55b0494..c2db196c77 100644 --- a/cpukit/libfs/src/dosfs/msdos_file.c +++ b/cpukit/libfs/src/dosfs/msdos_file.c @@ -64,8 +64,6 @@ msdos_file_open(rtems_libio_t *iop, const char *pathname, int oflag, if (iop->flags & LIBIO_FLAGS_APPEND) iop->offset = fat_fd->fat_file_size; - iop->size = fat_fd->fat_file_size; - rtems_semaphore_release(fs_info->vol_sema); 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) fat_fd->fat_file_size = iop->offset + ret; - iop->size = fat_fd->fat_file_size; - rtems_semaphore_release(fs_info->vol_sema); 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 -- * * PARAMETERS: @@ -332,7 +280,7 @@ msdos_file_ftruncate(rtems_libio_t *iop, off_t length) * file size only if length < 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); return RC_OK; diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_dir.c b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c index 193d796dd9..eeaa77d15e 100644 --- a/cpukit/libfs/src/dosfs/msdos_handlers_dir.c +++ b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c @@ -24,7 +24,7 @@ const rtems_filesystem_file_handlers_r msdos_dir_handlers = { msdos_dir_read, rtems_filesystem_default_write, rtems_filesystem_default_ioctl, - msdos_dir_lseek, + rtems_filesystem_default_lseek_directory, msdos_dir_stat, rtems_filesystem_default_ftruncate_directory, msdos_dir_sync, diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_file.c b/cpukit/libfs/src/dosfs/msdos_handlers_file.c index fefb6795d9..e68a09f1d3 100644 --- a/cpukit/libfs/src/dosfs/msdos_handlers_file.c +++ b/cpukit/libfs/src/dosfs/msdos_handlers_file.c @@ -24,7 +24,7 @@ const rtems_filesystem_file_handlers_r msdos_file_handlers = { msdos_file_read, msdos_file_write, rtems_filesystem_default_ioctl, - msdos_file_lseek, + rtems_filesystem_default_lseek_file, msdos_file_stat, msdos_file_ftruncate, msdos_file_sync, diff --git a/cpukit/libfs/src/imfs/deviceio.c b/cpukit/libfs/src/imfs/deviceio.c index c4e7a921ff..f18c9e7cee 100644 --- a/cpukit/libfs/src/imfs/deviceio.c +++ b/cpukit/libfs/src/imfs/deviceio.c @@ -191,23 +191,6 @@ int device_ioctl( 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 * diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h index dd7c158383..daad052f9d 100644 --- a/cpukit/libfs/src/imfs/imfs.h +++ b/cpukit/libfs/src/imfs/imfs.h @@ -418,12 +418,6 @@ extern ssize_t imfs_dir_read( 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( rtems_libio_t *iop, /* IN */ const char *pathname, /* IN */ @@ -449,12 +443,6 @@ extern int memfile_ioctl( void *buffer /* IN */ ); -extern off_t memfile_lseek( - rtems_libio_t *iop, /* IN */ - off_t offset, /* IN */ - int whence /* IN */ -); - extern int device_open( rtems_libio_t *iop, /* IN */ const char *pathname, /* IN */ @@ -484,12 +472,6 @@ extern int device_ioctl( void *buffer /* IN */ ); -extern off_t device_lseek( - rtems_libio_t *iop, /* IN */ - off_t offset, /* IN */ - int whence /* IN */ -); - extern int device_ftruncate( rtems_libio_t *iop, /* IN */ off_t length /* IN */ diff --git a/cpukit/libfs/src/imfs/imfs_directory.c b/cpukit/libfs/src/imfs/imfs_directory.c index c6be71ffcc..f77b68bc14 100644 --- a/cpukit/libfs/src/imfs/imfs_directory.c +++ b/cpukit/libfs/src/imfs/imfs_directory.c @@ -99,41 +99,3 @@ ssize_t imfs_dir_read( 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; -} diff --git a/cpukit/libfs/src/imfs/imfs_handlers_device.c b/cpukit/libfs/src/imfs/imfs_handlers_device.c index dfbd8949c5..fe3973df05 100644 --- a/cpukit/libfs/src/imfs/imfs_handlers_device.c +++ b/cpukit/libfs/src/imfs/imfs_handlers_device.c @@ -36,7 +36,7 @@ static const rtems_filesystem_file_handlers_r IMFS_device_handlers = { device_read, device_write, device_ioctl, - device_lseek, + rtems_filesystem_default_lseek_file, IMFS_stat_device, device_ftruncate, rtems_filesystem_default_fsync_or_fdatasync, diff --git a/cpukit/libfs/src/imfs/imfs_handlers_directory.c b/cpukit/libfs/src/imfs/imfs_handlers_directory.c index 9c3f77416a..579fdec2ea 100644 --- a/cpukit/libfs/src/imfs/imfs_handlers_directory.c +++ b/cpukit/libfs/src/imfs/imfs_handlers_directory.c @@ -52,7 +52,7 @@ static const rtems_filesystem_file_handlers_r IMFS_directory_handlers = { imfs_dir_read, rtems_filesystem_default_write, rtems_filesystem_default_ioctl, - imfs_dir_lseek, + rtems_filesystem_default_lseek_directory, IMFS_stat_directory, rtems_filesystem_default_ftruncate_directory, rtems_filesystem_default_fsync_or_fdatasync_success, diff --git a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c index 57d488af6f..262b93aa2a 100644 --- a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c +++ b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c @@ -36,7 +36,7 @@ static const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = { memfile_read, memfile_write, memfile_ioctl, - memfile_lseek, + rtems_filesystem_default_lseek_file, IMFS_stat_file, memfile_ftruncate, rtems_filesystem_default_fsync_or_fdatasync_success, diff --git a/cpukit/libfs/src/imfs/memfile.c b/cpukit/libfs/src/imfs/memfile.c index d2cff01517..64679df037 100644 --- a/cpukit/libfs/src/imfs/memfile.c +++ b/cpukit/libfs/src/imfs/memfile.c @@ -109,7 +109,6 @@ int memfile_open( if (iop->flags & LIBIO_FLAGS_APPEND) iop->offset = the_jnode->info.file.size; - iop->size = the_jnode->info.file.size; return 0; } @@ -148,7 +147,6 @@ ssize_t memfile_write( the_jnode = iop->pathinfo.node_access; status = IMFS_memfile_write( the_jnode, iop->offset, buffer, count ); - iop->size = the_jnode->info.file.size; return status; } @@ -169,34 +167,6 @@ int memfile_ioctl( 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 * @@ -232,7 +202,6 @@ int memfile_ftruncate( * future use and just set the length. */ the_jnode->info.file.size = length; - iop->size = the_jnode->info.file.size; IMFS_update_atime( the_jnode ); @@ -265,7 +234,7 @@ MEMFILE_STATIC int IMFS_memfile_extend( * Verify new file size is supported */ 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 @@ -654,7 +623,7 @@ MEMFILE_STATIC ssize_t IMFS_memfile_write( if ( last_byte > the_jnode->info.file.size ) { status = IMFS_memfile_extend( the_jnode, last_byte ); if ( status ) - rtems_set_errno_and_return_minus_one( ENOSPC ); + return status; } copied = 0; diff --git a/cpukit/libfs/src/nfsclient/src/nfs.c b/cpukit/libfs/src/nfsclient/src/nfs.c index 15b6def0d2..09a9278952 100644 --- a/cpukit/libfs/src/nfsclient/src/nfs.c +++ b/cpukit/libfs/src/nfsclient/src/nfs.c @@ -2424,63 +2424,25 @@ int e; 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( rtems_libio_t *iop, off_t length, int whence ) { -DirInfo di = iop->pathinfo.node_access_2; + off_t rv = rtems_filesystem_default_lseek_directory(iop, length, whence); - /* we don't support anything other than - * rewinding - */ - if (SEEK_SET != whence || 0 != length) { - errno = ENOTSUP; - return -1; - } + if (rv == 0) { + DirInfo di = iop->pathinfo.node_access_2; + nfscookie *cookie = &di->readdirargs.cookie; - /* rewind cookie */ - memset( &di->readdirargs.cookie, - 0, - sizeof(di->readdirargs.cookie) ); + di->eofreached = FALSE; - di->eofreached = FALSE; + /* rewind cookie */ + memset(cookie, 0, sizeof(*cookie)); + } - return iop->offset; + return rv; } #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, .write_h = nfs_file_write, .ioctl_h = rtems_filesystem_default_ioctl, - .lseek_h = nfs_file_lseek, + .lseek_h = rtems_filesystem_default_lseek_file, .fstat_h = nfs_fstat, .ftruncate_h = nfs_file_ftruncate, .fsync_h = rtems_filesystem_default_fsync_or_fdatasync, diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c index d66e4296c5..0325885d84 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c +++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c @@ -213,24 +213,6 @@ rtems_rfs_rtems_device_ioctl (rtems_libio_t* iop, 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. * @@ -255,7 +237,7 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_device_handlers = { .read_h = rtems_rfs_rtems_device_read, .write_h = rtems_rfs_rtems_device_write, .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, .ftruncate_h = rtems_rfs_rtems_device_ftruncate, .fsync_h = rtems_filesystem_default_fsync_or_fdatasync, diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c index 550973db0c..88f71e53a9 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c +++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c @@ -150,43 +150,6 @@ rtems_rfs_rtems_dir_read (rtems_libio_t* iop, 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. */ @@ -197,7 +160,7 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_dir_handlers = { .read_h = rtems_rfs_rtems_dir_read, .write_h = rtems_filesystem_default_write, .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, .ftruncate_h = rtems_filesystem_default_ftruncate_directory, .fsync_h = rtems_filesystem_default_fsync_or_fdatasync, diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c index 0a15652dfc..b2ff45df8b 100644 --- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c +++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c @@ -72,7 +72,6 @@ rtems_rfs_rtems_file_open (rtems_libio_t* iop, if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN)) 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_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)); return write; @@ -282,26 +279,32 @@ rtems_rfs_rtems_file_lseek (rtems_libio_t* iop, int whence) { rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop); - rtems_rfs_pos pos; - int rc; + off_t old_offset; + off_t new_offset; if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_LSEEK)) printf("rtems-rfs: file-lseek: handle:%p offset:%" PRIdoff_t "\n", file, offset); rtems_rfs_rtems_lock (rtems_rfs_file_fs (file)); - pos = iop->offset; - - rc = rtems_rfs_file_seek (file, pos, &pos); - if (rc) + old_offset = iop->offset; + new_offset = rtems_filesystem_default_lseek_file (iop, offset, whence); + if (new_offset != -1) { - rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file)); - return rtems_rfs_rtems_error ("file_lseek: lseek", rc); + rtems_rfs_pos pos = iop->offset; + int rc = rtems_rfs_file_seek (file, pos, &pos); + + if (rc) + { + rtems_rfs_rtems_error ("file_lseek: lseek", rc); + iop->offset = old_offset; + new_offset = -1; + } } 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) 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)); return rc; diff --git a/testsuites/fstests/fsrdwr/init.c b/testsuites/fstests/fsrdwr/init.c index ef2b02a0b8..8b40f07581 100644 --- a/testsuites/fstests/fsrdwr/init.c +++ b/testsuites/fstests/fsrdwr/init.c @@ -371,7 +371,7 @@ lseek_test (void) */ status = fstat (fd, &statbuf); 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); rtems_test_assert (status == 0); diff --git a/testsuites/psxtests/psximfs01/init.c b/testsuites/psxtests/psximfs01/init.c index c567eee10f..88796bac29 100644 --- a/testsuites/psxtests/psximfs01/init.c +++ b/testsuites/psxtests/psximfs01/init.c @@ -56,7 +56,7 @@ void write_helper(void) do { written = write( TestFd, Buffer, sizeof(Buffer) ); if ( written == -1 ) { - if ( errno == ENOSPC ) { + if ( errno == EFBIG ) { printf( "Total written = %zd\n", TotalWritten ); return; } @@ -93,22 +93,21 @@ void read_helper(void) rtems_test_exit(0); } i++; - continue; - } - /* Unsure if ENOSPC is the write error to be returned */ - if ( errno == ENOSPC && i == TotalWritten ) { - puts( "File correctly read until ENOSPC returned\n" ); - return; + } else if ( sc != 0 ) { + fprintf( + stderr, + "ERROR - at offset %d - returned %zd and error=%s\n", + i, + sc, + strerror( errno ) + ); + rtems_test_exit(0); } - fprintf( - stderr, - "ERROR - at offset %d - returned %zd and error=%s\n", - i, - sc, - strerror( errno ) - ); - rtems_test_exit(0); - } while (1); + } while ( sc > 0 ); + + if ( i == TotalWritten ) { + puts( "File correctly read until EOF returned\n" ); + } } void truncate_helper(void) @@ -143,7 +142,7 @@ void truncate_helper(void) } while (new > 0); } -void extend_helper(void) +void extend_helper(int eno) { off_t position; off_t new; @@ -164,18 +163,11 @@ void extend_helper(void) new = position; do { sc = lseek( TestFd, new, SEEK_SET ); - if( sc == -1 ) { - if( errno == ENOSPC ) { - break; - } - else { - rtems_test_assert( 0 ); - } - } + rtems_test_assert( sc == new ); rc = ftruncate( TestFd, new ); if ( rc != 0 ) { - if( errno != ENOSPC ) { + if( errno != eno ) { fprintf( stderr, "ERROR - at offset %d - returned %d and error=%s\n", @@ -218,8 +210,10 @@ rtems_task Init( { int i; void *alloc_ptr = (void *)0; - int position = 0; - int status = 0; + off_t position; + off_t new_position; + char buf [1]; + ssize_t n; puts( "\n\n*** TEST IMFS 01 ***" ); @@ -244,18 +238,21 @@ rtems_task Init( */ alloc_ptr = malloc( malloc_free_space() - 4 ); - extend_helper(); + extend_helper(ENOSPC); /* * free the allocated heap memory */ free(alloc_ptr); - extend_helper(); + extend_helper(EFBIG); position = lseek( TestFd , 0, SEEK_END ); - status = lseek( TestFd, position+2, SEEK_SET ); - rtems_test_assert( status == -1 ); - rtems_test_assert( errno == ENOSPC ); + new_position = lseek( TestFd, position + 2, SEEK_SET ); + rtems_test_assert( new_position == position + 2 ); + + n = write( TestFd, buf, sizeof(buf) ); + rtems_test_assert( n == -1 ); + rtems_test_assert( errno == EFBIG ); close_it(); unlink_it(); -- cgit v1.2.3