From eb9a4b9034453ae3093d678a6f3898303dc5a5a0 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Mon, 12 Jun 2023 18:32:12 +0200 Subject: 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 --- lib/io/src/unix/ostream.c | 102 ++++++++++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 35 deletions(-) (limited to 'lib/io/src/unix/ostream.c') 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; -- cgit v1.2.3