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