/* truncate the file to the specified length */ static int ftruncate_internal(struct filestr_desc *file, file_size_t size, bool write_now) { int rc = 0, rc2 = 1; file_size_t cursize = *file->sizep; file_size_t truncsize = MIN(size, cursize); if (write_now) { unsigned long sector = filesize_sectors(truncsize); struct filestr_cache *const cachep = file->stream.cachep; if (cachep->flags == (FSC_NEW|FSC_DIRTY) && cachep->sector + 1 == sector) { /* sector created but may have never been added to the cluster chain; flush it now or the subsequent may fail */ rc2 = flush_cache(file); if (rc2 == FAT_RC_ENOSPC) { /* no space left on device; further truncation needed */ discard_cache(file); truncsize = ALIGN_DOWN(truncsize - 1, SECTOR_SIZE); sector--; rc = rc2; } else if (rc2 < 0) FILE_ERROR(ERRNO, rc2 * 10 - 1); } rc2 = fat_seek(&file->stream.fatstr, sector); if (rc2 < 0) FILE_ERROR(EIO, rc2 * 10 - 2); rc2 = fat_truncate(&file->stream.fatstr); if (rc2 < 0) FILE_ERROR(EIO, rc2 * 10 - 3); } /* else just change the cached file size */ if (truncsize < cursize) { *file->sizep = truncsize; fileop_ontruncate_internal(&file->stream); } /* if truncation was partially successful, it effectively destroyed everything after the truncation point; still, indicate failure after adjusting size */ if (rc2 == 0) FILE_ERROR(EIO, -4); else if (rc2 < 0) FILE_ERROR(ERRNO, rc2); file_error: return rc; }
/* * Truncate a file to 0 length. */ static void UMSDOS_truncate (struct inode *inode) { Printk (("UMSDOS_truncate\n")); if (!IS_RDONLY (inode)) { fat_truncate (inode); inode->i_ctime = inode->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); } }