Ejemplo n.º 1
0
/* msdos_file_ftruncate --
 *     Truncate the file (if new length is greater then current do nothing).
 *
 * PARAMETERS:
 *     iop    - file control block
 *     length - new length
 *
 * RETURNS:
 *     RC_OK on success, or -1 if error occured (errno set appropriately).
 */
int
msdos_file_ftruncate(rtems_libio_t *iop, rtems_off64_t length)
{
    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;

    if (length >= fat_fd->fat_file_size)
        return RC_OK;

    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;
    }

    /*
     * 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;

    rtems_semaphore_release(fs_info->vol_sema);
    return RC_OK;
}
Ejemplo n.º 2
0
/* msdos_file_ftruncate --
 *     Truncate the file.
 *
 * PARAMETERS:
 *     iop    - file control block
 *     length - new length
 *
 * RETURNS:
 *     RC_OK on success, or -1 if error occured (errno set appropriately).
 */
int
msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
{
    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 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);

    old_length = fat_fd->fat_file_size;
    if (length < old_length) {
        rc = fat_file_truncate(&fs_info->fat, fat_fd, length);
    } else {
        uint32_t new_length;

        rc = fat_file_extend(&fs_info->fat,
                             fat_fd,
                             true,
                             length,
                             &new_length);
        if (rc == RC_OK && length != new_length) {
            fat_file_truncate(&fs_info->fat, fat_fd, old_length);
            errno = ENOSPC;
            rc = -1;
        }
    }

    if (rc == RC_OK)
    {
        fat_file_set_file_size(fat_fd, length);
        fat_file_set_ctime_mtime(fat_fd, time(NULL));
    }

    rtems_semaphore_release(fs_info->vol_sema);

    return rc;
}
Ejemplo n.º 3
0
/* fat_file_close --
 *     Close fat-file. If count of links to fat-file
 *     descriptor is greater than 1 (i.e. somebody esle holds pointer
 *     to this descriptor) just decrement it. Otherwise
 *     do the following. If this descriptor corresponded to removed fat-file
 *     then free clusters contained fat-file data, delete descriptor from
 *     "rhash" table and free memory allocated by descriptor. If descriptor
 *     correspondes to non-removed fat-file and 'ino' field has value from
 *     unique inode numbers pool then set count of links to descriptor to zero
 *     and leave it in hash, otherwise delete descriptor from "vhash" and free
 *     memory allocated by the descriptor
 *
 * PARAMETERS:
 *     mt_entry - mount table entry
 *     fat_fd   - fat-file descriptor
 *
 * RETURNS:
 *     RC_OK, or -1 if error occured (errno set appropriately)
 */
int
fat_file_close(
    rtems_filesystem_mount_table_entry_t *mt_entry,
    fat_file_fd_t                        *fat_fd
    )
{
    int            rc = RC_OK;
    fat_fs_info_t *fs_info = mt_entry->fs_info;
    uint32_t       key = 0;

    /*
     * if links_num field of fat-file descriptor is greater than 1
     * decrement the count of links and return
     */
    if (fat_fd->links_num > 1)
    {
        fat_fd->links_num--;
        return rc;
    }

    key = fat_construct_key(mt_entry, &fat_fd->dir_pos.sname);

    if (fat_fd->flags & FAT_FILE_REMOVED)
    {
        rc = fat_file_truncate(mt_entry, fat_fd, 0);
        if ( rc != RC_OK )
            return rc;

        _hash_delete(fs_info->rhash, key, fat_fd->ino, fat_fd);

        if ( fat_ino_is_unique(mt_entry, fat_fd->ino) )
            fat_free_unique_ino(mt_entry, fat_fd->ino);

        free(fat_fd);
    }
    else
    {
        if (fat_ino_is_unique(mt_entry, fat_fd->ino))
        {
            fat_fd->links_num = 0;
        }
        else
        {
            _hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
            free(fat_fd);
        }
    }
    /*
     * flush any modified "cached" buffer back to disk
     */
    rc = fat_buf_release(fs_info);

    return rc;
}