forked from Imagelibrary/rtems
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:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
@@ -19,11 +18,20 @@
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
off_t rtems_filesystem_default_lseek_success(
|
||||
off_t rtems_filesystem_default_lseek_directory(
|
||||
rtems_libio_t *iop,
|
||||
off_t offset,
|
||||
int whence
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
off_t rv = 0;
|
||||
|
||||
if ( offset == 0 && whence == SEEK_SET ) {
|
||||
iop->offset = 0;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
70
cpukit/libfs/src/defaults/default_lseek_file.c
Normal file
70
cpukit/libfs/src/defaults/default_lseek_file.c
Normal 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;
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
di->eofreached = FALSE;
|
||||
|
||||
/* rewind cookie */
|
||||
memset(cookie, 0, sizeof(*cookie));
|
||||
}
|
||||
|
||||
/* rewind cookie */
|
||||
memset( &di->readdirargs.cookie,
|
||||
0,
|
||||
sizeof(di->readdirargs.cookie) );
|
||||
|
||||
di->eofreached = FALSE;
|
||||
|
||||
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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
} else if ( sc != 0 ) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"ERROR - at offset %d - returned %zd and error=%s\n",
|
||||
i,
|
||||
sc,
|
||||
strerror( errno )
|
||||
);
|
||||
rtems_test_exit(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(
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user