diff options
Diffstat (limited to 'cpukit/libfs/src/dosfs/msdos_file.c')
-rw-r--r-- | cpukit/libfs/src/dosfs/msdos_file.c | 241 |
1 files changed, 55 insertions, 186 deletions
diff --git a/cpukit/libfs/src/dosfs/msdos_file.c b/cpukit/libfs/src/dosfs/msdos_file.c index 7cd55b0494..176ec8e8db 100644 --- a/cpukit/libfs/src/dosfs/msdos_file.c +++ b/cpukit/libfs/src/dosfs/msdos_file.c @@ -27,47 +27,38 @@ #include "msdos.h" -/* msdos_file_open -- - * Open fat-file which correspondes to the file - * - * PARAMETERS: - * iop - file control block - * pathname - name - * flag - flags - * mode - mode - * - * RETURNS: - * RC_OK, if file opened successfully, or -1 if error occured - * and errno set appropriately - */ -int -msdos_file_open(rtems_libio_t *iop, const char *pathname, int oflag, - mode_t mode) +static int +msdos_file_update(rtems_libio_t *iop) { - 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; - - 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); + int rc = RC_OK; + fat_file_fd_t *fat_fd = iop->pathinfo.node_access; - rc = fat_file_reopen(fat_fd); - if (rc != RC_OK) + /* + * if fat-file descriptor is not marked as "removed", synchronize + * size, first cluster number, write time and date fields of the file + */ + if (!FAT_FILE_IS_REMOVED(fat_fd)) { - rtems_semaphore_release(fs_info->vol_sema); - return rc; - } + rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd); + if (rc != RC_OK) + { + return rc; + } - if (iop->flags & LIBIO_FLAGS_APPEND) - iop->offset = fat_fd->fat_file_size; + rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd); + if (rc != RC_OK) + { + return rc; + } - iop->size = fat_fd->fat_file_size; + rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd); + if (rc != RC_OK) + { + return rc; + } + } - rtems_semaphore_release(fs_info->vol_sema); - return RC_OK; + return rc; } /* msdos_file_close -- @@ -88,42 +79,13 @@ msdos_file_close(rtems_libio_t *iop) 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; 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); - /* - * if fat-file descriptor is not marked as "removed", synchronize - * size, first cluster number, write time and date fields of the file - */ - if (!FAT_FILE_IS_REMOVED(fat_fd)) - { - rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd); - if (rc != RC_OK) - { - rtems_semaphore_release(fs_info->vol_sema); - return rc; - } - - rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd); - if (rc != RC_OK) - { - rtems_semaphore_release(fs_info->vol_sema); - return rc; - } - - rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd); - if (rc != RC_OK) - { - rtems_semaphore_release(fs_info->vol_sema); - return rc; - } - } - - rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd); + rc = msdos_file_update(iop); rtems_semaphore_release(fs_info->vol_sema); return rc; @@ -188,6 +150,9 @@ msdos_file_write(rtems_libio_t *iop,const void *buffer, size_t count) if (sc != RTEMS_SUCCESSFUL) rtems_set_errno_and_return_minus_one(EIO); + if ((iop->flags & LIBIO_FLAGS_APPEND) != 0) + iop->offset = fat_fd->fat_file_size; + ret = fat_file_write(iop->pathinfo.mt_entry, fat_fd, iop->offset, count, buffer); if (ret < 0) @@ -203,60 +168,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: @@ -295,7 +210,7 @@ msdos_file_stat( } /* msdos_file_ftruncate -- - * Truncate the file (if new length is greater then current do nothing). + * Truncate the file. * * PARAMETERS: * iop - file control block @@ -311,31 +226,38 @@ msdos_file_ftruncate(rtems_libio_t *iop, off_t length) 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; - - if (length >= fat_fd->fat_file_size) - return RC_OK; + uint32_t old_length; 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_truncate(iop->pathinfo.mt_entry, fat_fd, length); - if (rc != RC_OK) - { - rtems_semaphore_release(fs_info->vol_sema); - return rc; + old_length = fat_fd->fat_file_size; + if (length < old_length) { + rc = fat_file_truncate(iop->pathinfo.mt_entry, fat_fd, length); + } else { + uint32_t new_length; + + rc = fat_file_extend(iop->pathinfo.mt_entry, + fat_fd, + true, + length, + &new_length); + if (rc == RC_OK && length != new_length) { + fat_file_truncate(iop->pathinfo.mt_entry, fat_fd, old_length); + errno = ENOSPC; + rc = -1; + } } - /* - * fat_file_truncate do nothing if new length >= fat-file size, so update - * file size only if length < fat-file size - */ - if (length < fat_fd->fat_file_size) - iop->size = fat_fd->fat_file_size = length; + if (rc == RC_OK) { + fat_fd->fat_file_size = length; + } rtems_semaphore_release(fs_info->vol_sema); - return RC_OK; + + return rc; } /* msdos_file_sync -- @@ -361,67 +283,14 @@ msdos_file_sync(rtems_libio_t *iop) if (sc != RTEMS_SUCCESSFUL) rtems_set_errno_and_return_minus_one(EIO); - /* synchronize file data */ - rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd); + rc = msdos_file_update(iop); if (rc != RC_OK) { rtems_semaphore_release(fs_info->vol_sema); return rc; } - /* - * if fat-file descriptor is not marked "removed" - synchronize file - * metadata - */ - if (!FAT_FILE_IS_REMOVED(fat_fd)) - { - rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd); - if (rc != RC_OK) - { - rtems_semaphore_release(fs_info->vol_sema); - return rc; - } - rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd); - if (rc != RC_OK) - { - rtems_semaphore_release(fs_info->vol_sema); - return rc; - } - rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd); - if (rc != RC_OK) - { - rtems_semaphore_release(fs_info->vol_sema); - return rc; - } - } - - rtems_semaphore_release(fs_info->vol_sema); - return RC_OK; -} - -/* msdos_file_datasync -- - * Synchronize file - synchronize only file data (metadata is letf intact). - * - * PARAMETERS: - * iop - file control block - * - * RETURNS: - * RC_OK on success, or -1 if error occured (errno set appropriately) - */ -int -msdos_file_datasync(rtems_libio_t *iop) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - fat_file_fd_t *fat_fd = iop->pathinfo.node_access; - msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info; - - 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); - - /* synchronize file data */ - fat_file_datasync(iop->pathinfo.mt_entry, fat_fd); + rc = msdos_sync_unprotected(fs_info); rtems_semaphore_release(fs_info->vol_sema); return RC_OK; |