summaryrefslogtreecommitdiffstats
path: root/cpukit/libfs/src/dosfs/msdos_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libfs/src/dosfs/msdos_file.c')
-rw-r--r--cpukit/libfs/src/dosfs/msdos_file.c241
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;