Added lfs_file_truncate

As a copy-on-write filesystem, the truncate function is a very nice
function to have, as it can take advantage of reusing the data already
written out to disk.
This commit is contained in:
Christopher Haster
2018-01-20 17:30:40 -06:00
parent 2ad435ed63
commit d88f0ac02f
4 changed files with 195 additions and 2 deletions

57
lfs.c
View File

@@ -1664,6 +1664,57 @@ lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
return file->pos;
}
int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
if ((file->flags & 3) == LFS_O_RDONLY) {
return LFS_ERR_INVAL;
}
if (size < lfs_file_size(lfs, file)) {
// need to flush since directly changing metadata
int err = lfs_file_flush(lfs, file);
if (err) {
return err;
}
// lookup new head in ctz skip list
err = lfs_ctz_find(lfs, &file->cache, NULL,
file->head, file->size,
size, &file->head, &(lfs_off_t){0});
if (err) {
return err;
}
file->size = size;
file->flags |= LFS_F_DIRTY;
} else if (size > lfs_file_size(lfs, file)) {
lfs_off_t pos = file->pos;
// flush+seek if not already at end
if (file->pos != lfs_file_size(lfs, file)) {
int err = lfs_file_seek(lfs, file, 0, SEEK_END);
if (err) {
return err;
}
}
// fill with zeros
while (file->pos < size) {
lfs_ssize_t res = lfs_file_write(lfs, file, &(uint8_t){0}, 1);
if (res < 0) {
return res;
}
}
// restore pos
int err = lfs_file_seek(lfs, file, pos, LFS_SEEK_SET);
if (err < 0) {
return err;
}
}
return 0;
}
lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) {
return file->pos;
}
@@ -1678,7 +1729,11 @@ int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file) {
}
lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
return lfs_max(file->pos, file->size);
if (file->flags & LFS_F_WRITING) {
return lfs_max(file->pos, file->size);
} else {
return file->size;
}
}