aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-09-25 18:25:33 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-09-29 15:33:15 +0200
commit897a625cacdd9201f9f2531f5ce97c4ab5e5d90a (patch)
treed85c5bc5f654425630c1b274a27ca0ad18b5d9e3
parentfdefb8d09adf74635ad00883a1389361aa4740dc (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.c40
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)