diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2022-06-26 22:51:27 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2022-07-08 19:17:35 +0200 |
commit | 359d71e90050a8b83f7bc7d2ecd4ff29c477cc22 (patch) | |
tree | df2b7a585b78e6776446d4ca9be62a22db27f0a7 /lib/io/win32/ostream.c | |
parent | 2087cc237cd0fe1ed29ebf891648bacb46f4833b (diff) |
Cleanup: rename libfstream to libio, split headers
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/io/win32/ostream.c')
-rw-r--r-- | lib/io/win32/ostream.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/lib/io/win32/ostream.c b/lib/io/win32/ostream.c new file mode 100644 index 0000000..2bd78c8 --- /dev/null +++ b/lib/io/win32/ostream.c @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * ostream.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "../internal.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +typedef struct { + ostream_t base; + char *path; + HANDLE hnd; +} file_ostream_t; + +static int w32_append(HANDLE hnd, const char *filename, + const void *data, size_t size) +{ + DWORD diff; + + while (size > 0) { + if (!WriteFile(hnd, data, size, &diff, NULL)) { + w32_perror(filename); + return -1; + } + + size -= diff; + data = (const char *)data + diff; + } + + return 0; +} + +static int w32_flush(HANDLE hnd, const char *filename) +{ + if (!FlushFileBuffers(hnd)) { + w32_perror(filename); + return -1; + } + + return 0; +} + +/*****************************************************************************/ + +static int file_append(ostream_t *strm, const void *data, size_t size) +{ + file_ostream_t *file = (file_ostream_t *)strm; + + return w32_append(file->hnd, file->path, data, size); +} + +static int file_append_sparse(ostream_t *strm, size_t size) +{ + file_ostream_t *file = (file_ostream_t *)strm; + LARGE_INTEGER pos; + + pos.QuadPart = size; + + if (!SetFilePointerEx(file->hnd, pos, NULL, FILE_CURRENT)) + goto fail; + + if (!SetEndOfFile(file->hnd)) + goto fail; + + return 0; +fail: + w32_perror(file->path); + return -1; +} + +static int file_flush(ostream_t *strm) +{ + file_ostream_t *file = (file_ostream_t *)strm; + + return w32_flush(file->hnd, file->path); +} + +static void file_destroy(sqfs_object_t *obj) +{ + file_ostream_t *file = (file_ostream_t *)obj; + + CloseHandle(file->hnd); + free(file->path); + free(file); +} + +static const char *file_get_filename(ostream_t *strm) +{ + file_ostream_t *file = (file_ostream_t *)strm; + + return file->path; +} + +/*****************************************************************************/ + +static int stdout_append(ostream_t *strm, const void *data, size_t size) +{ + (void)strm; + return w32_append(GetStdHandle(STD_OUTPUT_HANDLE), "stdout", + data, size); +} + +static int stdout_flush(ostream_t *strm) +{ + (void)strm; + return w32_flush(GetStdHandle(STD_OUTPUT_HANDLE), "stdout"); +} + +static void stdout_destroy(sqfs_object_t *obj) +{ + free(obj); +} + +static const char *stdout_get_filename(ostream_t *strm) +{ + (void)strm; + return "stdout"; +} + +/*****************************************************************************/ + +ostream_t *ostream_open_file(const char *path, int flags) +{ + file_ostream_t *file = calloc(1, sizeof(*file)); + sqfs_object_t *obj = (sqfs_object_t *)file; + ostream_t *strm = (ostream_t *)file; + int access_flags, creation_mode; + WCHAR *wpath = NULL; + + if (file == NULL) { + perror(path); + return NULL; + } + + wpath = path_to_windows(path); + if (wpath == NULL) + goto fail_free; + + file->path = strdup(path); + if (file->path == NULL) { + perror(path); + goto fail_free; + } + + access_flags = GENERIC_WRITE; + + if (flags & OSTREAM_OPEN_OVERWRITE) { + creation_mode = CREATE_ALWAYS; + } else { + creation_mode = CREATE_NEW; + } + + file->hnd = CreateFileW(wpath, access_flags, 0, NULL, creation_mode, + FILE_ATTRIBUTE_NORMAL, NULL); + + if (file->hnd == INVALID_HANDLE_VALUE) { + w32_perror(path); + goto fail_path; + } + + free(wpath); + + if (flags & OSTREAM_OPEN_SPARSE) + strm->append_sparse = file_append_sparse; + + strm->append = file_append; + strm->flush = file_flush; + strm->get_filename = file_get_filename; + obj->destroy = file_destroy; + return strm; +fail_path: + free(file->path); +fail_free: + free(file); + free(wpath); + return NULL; +} + +ostream_t *ostream_open_stdout(void) +{ + ostream_t *strm = calloc(1, sizeof(*strm)); + sqfs_object_t *obj = (sqfs_object_t *)strm; + + if (strm == NULL) { + perror("creating stdout file wrapper"); + return NULL; + } + + strm->append = stdout_append; + strm->flush = stdout_flush; + strm->get_filename = stdout_get_filename; + obj->destroy = stdout_destroy; + return strm; +} |