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/win32/ostream.c | 74 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 12 deletions(-) (limited to 'lib/io/src/win32') diff --git a/lib/io/src/win32/ostream.c b/lib/io/src/win32/ostream.c index d18130f..9b488d8 100644 --- a/lib/io/src/win32/ostream.c +++ b/lib/io/src/win32/ostream.c @@ -11,13 +11,14 @@ typedef struct { ostream_t base; + sqfs_u64 sparse_count; char *path; HANDLE hnd; + int flags; } file_ostream_t; -static int file_append(ostream_t *strm, const void *data, size_t size) +static int write_data(file_ostream_t *file, const void *data, size_t size) { - file_ostream_t *file = (file_ostream_t *)strm; DWORD diff; while (size > 0) { @@ -33,18 +34,48 @@ static int file_append(ostream_t *strm, const void *data, size_t size) return 0; } -static int file_append_sparse(ostream_t *strm, size_t size) +static int realize_sparse(file_ostream_t *file) { - file_ostream_t *file = (file_ostream_t *)strm; + size_t bufsz, diff; LARGE_INTEGER pos; + void *buffer; + + if (file->sparse_count == 0) + return 0; - pos.QuadPart = size; + if (file->flags & OSTREAM_OPEN_SPARSE) { + pos.QuadPart = file->sparse_count; - if (!SetFilePointerEx(file->hnd, pos, NULL, FILE_CURRENT)) - goto fail; + if (!SetFilePointerEx(file->hnd, pos, NULL, FILE_CURRENT)) + goto fail; - if (!SetEndOfFile(file->hnd)) - goto fail; + if (!SetEndOfFile(file->hnd)) + goto fail; + + file->sparse_count = 0; + } else { + bufsz = file->sparse_count > 1024 ? 1024 : file->sparse_count; + buffer = calloc(1, bufsz); + + if (buffer == NULL) { + fputs("out-of-memory\n", stderr); + return -1; + } + + while (file->sparse_count > 0) { + diff = file->sparse_count > bufsz ? + bufsz : file->sparse_count; + + if (write_data(file, buffer, diff)) { + free(buffer); + return -1; + } + + file->sparse_count -= diff; + } + + free(buffer); + } return 0; fail: @@ -52,10 +83,31 @@ fail: return -1; } +static int file_append(ostream_t *strm, const void *data, size_t size) +{ + file_ostream_t *file = (file_ostream_t *)strm; + + if (size == 0) + return 0; + + if (data == NULL) { + file->sparse_count += size; + return 0; + } + + if (realize_sparse(file)) + return -1; + + return write_data(file, data, size); +} + static int file_flush(ostream_t *strm) { file_ostream_t *file = (file_ostream_t *)strm; + if (realize_sparse(file)) + return -1; + if (!FlushFileBuffers(file->hnd)) { w32_perror(file->path); return -1; @@ -109,9 +161,7 @@ ostream_t *ostream_open_handle(const char *path, HANDLE hnd, int flags) CloseHandle(hnd); - 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