diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-06-12 18:32:12 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-06-15 13:38:25 +0200 |
commit | eb9a4b9034453ae3093d678a6f3898303dc5a5a0 (patch) | |
tree | cd024b5ff5e1c77400a561adee50522f10fdadcd /lib/io/src/unix | |
parent | 63bc750fecb00fc5878ca889204fc65510893778 (diff) |
libio: remove ostream_append_sparse and fallback implementation
Instead of a separate append-sparse function, simply accept NULL
as an input for append. For both Unix and Win32, a fallback needs
to be implemented. For XFRM, we can just memset the input buffer
to zero, same for the libsquashfs data writer.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/io/src/unix')
-rw-r--r-- | lib/io/src/unix/ostream.c | 102 |
1 files changed, 67 insertions, 35 deletions
diff --git a/lib/io/src/unix/ostream.c b/lib/io/src/unix/ostream.c index 294a15e..702a354 100644 --- a/lib/io/src/unix/ostream.c +++ b/lib/io/src/unix/ostream.c @@ -9,81 +9,115 @@ typedef struct { ostream_t base; char *path; + int flags; 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) +static int write_all(file_ostream_t *file, const sqfs_u8 *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); + ssize_t ret = write(file->fd, data, size); if (ret == 0) { - fprintf(stderr, "%s: truncated data write.\n", - file->path); + fprintf(stderr, "%s: truncated write.\n", file->path); return -1; } if (ret < 0) { if (errno == EINTR) continue; - goto fail_errno; + perror(file->path); + return -1; } file->size += ret; size -= ret; - data = (const char *)data + ret; + data += ret; + } + + return 0; +} + +static int realize_sparse(file_ostream_t *file) +{ + unsigned char *buffer; + size_t diff, bufsz; + + if (file->sparse_count == 0) + return 0; + + if (file->flags & OSTREAM_OPEN_SPARSE) { + if (lseek(file->fd, file->sparse_count, SEEK_CUR) == (off_t)-1) + goto fail; + + if (ftruncate(file->fd, file->size) != 0) + goto fail; + + file->sparse_count = 0; + } else { + bufsz = file->sparse_count > 1024 ? 1024 : file->sparse_count; + buffer = calloc(1, bufsz); + if (buffer == NULL) + goto fail; + + while (file->sparse_count > 0) { + diff = file->sparse_count > (off_t)bufsz ? + bufsz : (size_t)file->sparse_count; + + if (write_all(file, buffer, diff)) { + free(buffer); + return -1; + } + + file->sparse_count -= diff; + } + + free(buffer); } return 0; -fail_errno: +fail: perror(file->path); return -1; } -static int file_append_sparse(ostream_t *strm, size_t size) +static int file_append(ostream_t *strm, const void *data, size_t size) { file_ostream_t *file = (file_ostream_t *)strm; - file->sparse_count += size; - file->size += size; - return 0; + if (size == 0) + return 0; + + if (data == NULL) { + file->sparse_count += size; + file->size += size; + return 0; + } + + if (realize_sparse(file)) + return -1; + + return write_all(file, data, size); } static int file_flush(ostream_t *strm) { file_ostream_t *file = (file_ostream_t *)strm; - if (file->sparse_count > 0) { - if (ftruncate(file->fd, file->size) != 0) - goto fail; - } + if (realize_sparse(file)) + return -1; if (fsync(file->fd) != 0) { if (errno == EINVAL) return 0; - goto fail; + perror(file->path); + return -1; } return 0; -fail: - perror(file->path); - return -1; } static void file_destroy(sqfs_object_t *obj) @@ -128,9 +162,7 @@ ostream_t *ostream_open_handle(const char *path, int fd, int flags) close(fd); - if (flags & OSTREAM_OPEN_SPARSE) - strm->append_sparse = file_append_sparse; - + file->flags = flags; strm->append = file_append; strm->flush = file_flush; strm->get_filename = file_get_filename; |