diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-09-25 18:25:33 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-09-29 15:33:15 +0200 |
commit | 897a625cacdd9201f9f2531f5ce97c4ab5e5d90a (patch) | |
tree | d85c5bc5f654425630c1b274a27ca0ad18b5d9e3 | |
parent | fdefb8d09adf74635ad00883a1389361aa4740dc (diff) |
libfstream: Rework unix sparse file writing
Instead of immediately seeking forward, record the sparse bytes "written"
and then do the seek the next time we write data, or do an ftruncate if
we do a sync.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r-- | lib/fstream/unix/ostream.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/lib/fstream/unix/ostream.c b/lib/fstream/unix/ostream.c index dac675f..84a5725 100644 --- a/lib/fstream/unix/ostream.c +++ b/lib/fstream/unix/ostream.c @@ -10,6 +10,9 @@ typedef struct { ostream_t base; char *path; int fd; + + off_t sparse_count; + off_t size; } file_ostream_t; static int file_append(ostream_t *strm, const void *data, size_t size) @@ -17,6 +20,16 @@ static int file_append(ostream_t *strm, const void *data, size_t size) file_ostream_t *file = (file_ostream_t *)strm; ssize_t ret; + if (size == 0) + return 0; + + if (file->sparse_count > 0) { + if (lseek(file->fd, file->sparse_count, SEEK_CUR) == (off_t)-1) + goto fail_errno; + + file->sparse_count = 0; + } + while (size > 0) { ret = write(file->fd, data, size); @@ -29,27 +42,26 @@ static int file_append(ostream_t *strm, const void *data, size_t size) if (ret < 0) { if (errno == EINTR) continue; - - perror(file->path); - return -1; + goto fail_errno; } + file->size += ret; size -= ret; data = (const char *)data + ret; } return 0; +fail_errno: + perror(file->path); + return -1; } static int file_append_sparse(ostream_t *strm, size_t size) { file_ostream_t *file = (file_ostream_t *)strm; - if (lseek(file->fd, size, SEEK_CUR) == (off_t)-1) { - perror(file->path); - return -1; - } - + file->sparse_count += size; + file->size += size; return 0; } @@ -57,12 +69,18 @@ static int file_flush(ostream_t *strm) { file_ostream_t *file = (file_ostream_t *)strm; - if (fsync(file->fd) != 0) { - perror(file->path); - return -1; + if (file->sparse_count > 0) { + if (ftruncate(file->fd, file->size) != 0) + goto fail; } + if (fsync(file->fd) != 0) + goto fail; + return 0; +fail: + perror(file->path); + return -1; } static void file_destroy(sqfs_object_t *obj) |