From c81e80bf35874696d9735f70e5c8327f92b5aca4 Mon Sep 17 00:00:00 2001
From: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Date: Fri, 16 Jun 2023 01:41:06 +0200
Subject: libsquashfs: merge windows & unix file I/O primitives

By adding additional close/duplicate primitives, the remaining, mostly
identical istream/ostream/file code is mostly identical between Windows
and Unix and be merged, mostly without stitches.

Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
---
 lib/sqfs/src/win32/io_file.c | 271 -------------------------------------------
 lib/sqfs/src/win32/istream.c | 190 ------------------------------
 lib/sqfs/src/win32/ostream.c | 201 --------------------------------
 3 files changed, 662 deletions(-)
 delete mode 100644 lib/sqfs/src/win32/io_file.c
 delete mode 100644 lib/sqfs/src/win32/istream.c
 delete mode 100644 lib/sqfs/src/win32/ostream.c

(limited to 'lib/sqfs/src/win32')

diff --git a/lib/sqfs/src/win32/io_file.c b/lib/sqfs/src/win32/io_file.c
deleted file mode 100644
index 4d76b94..0000000
--- a/lib/sqfs/src/win32/io_file.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * io_file.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#define SQFS_BUILDING_DLL
-#include "config.h"
-
-#include "sqfs/io.h"
-#include "sqfs/error.h"
-#include "compat.h"
-
-#include <stdlib.h>
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-
-typedef struct {
-	sqfs_file_t base;
-
-	bool readonly;
-	sqfs_u64 size;
-	sqfs_file_handle_t fd;
-
-	char name[];
-} sqfs_file_stdio_t;
-
-
-static void stdio_destroy(sqfs_object_t *base)
-{
-	sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base;
-
-	CloseHandle(file->fd);
-	free(file);
-}
-
-static sqfs_object_t *stdio_copy(const sqfs_object_t *base)
-{
-	const sqfs_file_stdio_t *file = (const sqfs_file_stdio_t *)base;
-	sqfs_file_stdio_t *copy;
-	size_t size;
-	BOOL ret;
-
-	if (!file->readonly) {
-		SetLastError(ERROR_NOT_SUPPORTED);
-		return NULL;
-	}
-
-	size = sizeof(*file) + strlen(file->name) + 1;
-	copy = calloc(1, size);
-	if (copy == NULL)
-		return NULL;
-
-	memcpy(copy, file, size);
-
-	ret = DuplicateHandle(GetCurrentProcess(), file->fd,
-			      GetCurrentProcess(), &copy->fd,
-			      0, FALSE, DUPLICATE_SAME_ACCESS);
-
-	if (!ret) {
-		os_error_t err = get_os_error_state();
-		free(copy);
-		set_os_error_state(err);
-		return NULL;
-	}
-
-	return (sqfs_object_t *)copy;
-}
-
-static int stdio_read_at(sqfs_file_t *base, sqfs_u64 offset,
-			 void *buffer, size_t size)
-{
-	sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base;
-	DWORD actually_read;
-	LARGE_INTEGER pos;
-
-	if (offset >= file->size)
-		return SQFS_ERROR_OUT_OF_BOUNDS;
-
-	if (size == 0)
-		return 0;
-
-	if ((offset + size - 1) >= file->size)
-		return SQFS_ERROR_OUT_OF_BOUNDS;
-
-	pos.QuadPart = offset;
-
-	if (!SetFilePointerEx(file->fd, pos, NULL, FILE_BEGIN))
-		return SQFS_ERROR_IO;
-
-	while (size > 0) {
-		if (!ReadFile(file->fd, buffer, size, &actually_read, NULL))
-			return SQFS_ERROR_IO;
-
-		size -= actually_read;
-		buffer = (char *)buffer + actually_read;
-	}
-
-	return 0;
-}
-
-static int stdio_write_at(sqfs_file_t *base, sqfs_u64 offset,
-			  const void *buffer, size_t size)
-{
-	sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base;
-	DWORD actually_read;
-	LARGE_INTEGER pos;
-
-	if (size == 0)
-		return 0;
-
-	pos.QuadPart = offset;
-
-	if (!SetFilePointerEx(file->fd, pos, NULL, FILE_BEGIN))
-		return SQFS_ERROR_IO;
-
-	while (size > 0) {
-		if (!WriteFile(file->fd, buffer, size, &actually_read, NULL))
-			return SQFS_ERROR_IO;
-
-		size -= actually_read;
-		buffer = (char *)buffer + actually_read;
-		offset += actually_read;
-
-		if (offset > file->size)
-			file->size = offset;
-	}
-
-	return 0;
-}
-
-static sqfs_u64 stdio_get_size(const sqfs_file_t *base)
-{
-	const sqfs_file_stdio_t *file = (const sqfs_file_stdio_t *)base;
-
-	return file->size;
-}
-
-static int stdio_truncate(sqfs_file_t *base, sqfs_u64 size)
-{
-	sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base;
-	LARGE_INTEGER pos;
-
-	pos.QuadPart = size;
-
-	if (!SetFilePointerEx(file->fd, pos, NULL, FILE_BEGIN))
-		return SQFS_ERROR_IO;
-
-	if (!SetEndOfFile(file->fd))
-		return SQFS_ERROR_IO;
-
-	file->size = size;
-	return 0;
-}
-
-static const char *stdio_get_filename(sqfs_file_t *file)
-{
-	return ((sqfs_file_stdio_t *)file)->name;
-}
-
-int sqfs_open_native_file(sqfs_file_handle_t *out, const char *filename,
-			  sqfs_u32 flags)
-{
-	int access_flags, creation_mode, share_mode;
-	WCHAR *wpath = NULL;
-	os_error_t err;
-	DWORD length;
-
-	*out = INVALID_HANDLE_VALUE;
-
-	if (flags & ~SQFS_FILE_OPEN_ALL_FLAGS) {
-		SetLastError(ERROR_INVALID_PARAMETER);
-		return SQFS_ERROR_UNSUPPORTED;
-	}
-
-	if (flags & SQFS_FILE_OPEN_READ_ONLY) {
-		access_flags = GENERIC_READ;
-		creation_mode = OPEN_EXISTING;
-		share_mode = FILE_SHARE_READ;
-	} else {
-		access_flags = GENERIC_READ | GENERIC_WRITE;
-		share_mode = 0;
-
-		if (flags & SQFS_FILE_OPEN_OVERWRITE) {
-			creation_mode = CREATE_ALWAYS;
-		} else {
-			creation_mode = CREATE_NEW;
-		}
-	}
-
-	if (flags & SQFS_FILE_OPEN_NO_CHARSET_XFRM) {
-		*out = CreateFileA(filename, access_flags, share_mode, NULL,
-				   creation_mode, FILE_ATTRIBUTE_NORMAL, NULL);
-	} else {
-		length = MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
-		if (length <= 0)
-			return SQFS_ERROR_INTERNAL;
-
-		wpath = calloc(sizeof(wpath[0]), length + 1);
-		if (wpath == NULL) {
-			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-			return SQFS_ERROR_ALLOC;
-		}
-
-		MultiByteToWideChar(CP_UTF8, 0, filename, -1,
-				    wpath, length + 1);
-		wpath[length] = '\0';
-
-		*out = CreateFileW(wpath, access_flags, share_mode, NULL,
-				   creation_mode, FILE_ATTRIBUTE_NORMAL,
-				   NULL);
-
-		err = get_os_error_state();
-		free(wpath);
-		set_os_error_state(err);
-	}
-
-	return (*out == INVALID_HANDLE_VALUE) ? SQFS_ERROR_IO : 0;
-}
-
-sqfs_file_t *sqfs_open_file(const char *filename, sqfs_u32 flags)
-{
-	sqfs_file_stdio_t *file;
-	size_t namelen, total;
-	LARGE_INTEGER size;
-	sqfs_file_t *base;
-	os_error_t err;
-
-	namelen = strlen(filename);
-	total = sizeof(*file) + 1;
-
-	if (SZ_ADD_OV(total, namelen, &total)) {
-		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-		return NULL;
-	}
-
-	file = calloc(1, total);
-	base = (sqfs_file_t *)file;
-	if (file == NULL) {
-		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-		return NULL;
-	}
-
-	sqfs_object_init(file, stdio_destroy, stdio_copy);
-	memcpy(file->name, filename, namelen);
-
-	if (sqfs_open_native_file(&file->fd, filename, flags))
-		goto fail;
-
-	if (!GetFileSizeEx(file->fd, &size))
-		goto fail;
-
-	file->size = size.QuadPart;
-	file->readonly = (flags & SQFS_FILE_OPEN_READ_ONLY) != 0;
-
-	base->read_at = stdio_read_at;
-	base->write_at = stdio_write_at;
-	base->get_size = stdio_get_size;
-	base->truncate = stdio_truncate;
-	base->get_filename = stdio_get_filename;
-	return base;
-fail:
-	err = get_os_error_state();
-	if (file->fd != INVALID_HANDLE_VALUE)
-		CloseHandle(file->fd);
-	free(file);
-	set_os_error_state(err);
-	return NULL;
-}
diff --git a/lib/sqfs/src/win32/istream.c b/lib/sqfs/src/win32/istream.c
deleted file mode 100644
index aeb3352..0000000
--- a/lib/sqfs/src/win32/istream.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * istream.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#define SQFS_BUILDING_DLL
-#include "config.h"
-
-#include "sqfs/io.h"
-#include "sqfs/error.h"
-
-#define BUFSZ (131072)
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <assert.h>
-
-typedef struct {
-	sqfs_istream_t base;
-	char *path;
-	HANDLE hnd;
-
-	bool eof;
-	size_t buffer_offset;
-	size_t buffer_used;
-	sqfs_u8 buffer[BUFSZ];
-} file_istream_t;
-
-static int precache(sqfs_istream_t *strm)
-{
-	file_istream_t *file = (file_istream_t *)strm;
-	DWORD diff, actual;
-
-	if (file->eof)
-		return 0;
-
-	if (file->buffer_offset > 0 &&
-	    file->buffer_offset < file->buffer_used) {
-		memmove(file->buffer, file->buffer + file->buffer_offset,
-			file->buffer_used - file->buffer_offset);
-	}
-
-	file->buffer_used -= file->buffer_offset;
-	file->buffer_offset = 0;
-
-	while (file->buffer_used < sizeof(file->buffer)) {
-		diff = sizeof(file->buffer) - file->buffer_used;
-
-		if (!ReadFile(file->hnd, file->buffer + file->buffer_used,
-			      diff, &actual, NULL)) {
-			os_error_t error = get_os_error_state();
-
-			if (error.w32_errno == ERROR_HANDLE_EOF ||
-			    error.w32_errno == ERROR_BROKEN_PIPE) {
-				file->eof = true;
-				break;
-			}
-
-			set_os_error_state(error);
-			return SQFS_ERROR_IO;
-		}
-
-		if (actual == 0) {
-			file->eof = true;
-			break;
-		}
-
-		file->buffer_used += actual;
-	}
-
-	return 0;
-}
-
-static int file_get_buffered_data(sqfs_istream_t *strm, const sqfs_u8 **out,
-				  size_t *size, size_t want)
-{
-	file_istream_t *file = (file_istream_t *)strm;
-
-	if (want > BUFSZ)
-		want = BUFSZ;
-
-	if (file->buffer_used == 0 ||
-	    (file->buffer_used - file->buffer_offset) < want) {
-		int ret = precache(strm);
-		if (ret)
-			return ret;
-	}
-
-	*out = file->buffer + file->buffer_offset;
-	*size = file->buffer_used - file->buffer_offset;
-	return (file->eof && *size == 0) ? 1 : 0;
-}
-
-static void file_advance_buffer(sqfs_istream_t *strm, size_t count)
-{
-	file_istream_t *file = (file_istream_t *)strm;
-
-	assert(count <= file->buffer_used);
-
-	file->buffer_offset += count;
-
-	assert(file->buffer_offset <= file->buffer_used);
-}
-
-static const char *file_get_filename(sqfs_istream_t *strm)
-{
-	return ((file_istream_t *)strm)->path;
-}
-
-static void file_destroy(sqfs_object_t *obj)
-{
-	file_istream_t *file = (file_istream_t *)obj;
-
-	CloseHandle(file->hnd);
-	free(file->path);
-	free(file);
-}
-
-int sqfs_istream_open_handle(sqfs_istream_t **out, const char *path,
-			     sqfs_file_handle_t hnd, sqfs_u32 flags)
-{
-	file_istream_t *file;
-	sqfs_istream_t *strm;
-	BOOL ret;
-
-	if (flags & ~(SQFS_FILE_OPEN_ALL_FLAGS))
-		return SQFS_ERROR_UNSUPPORTED;
-
-	file = calloc(1, sizeof(*file));
-	strm = (sqfs_istream_t *)file;
-	if (file == NULL)
-		return SQFS_ERROR_ALLOC;
-
-	sqfs_object_init(file, file_destroy, NULL);
-
-	file->path = strdup(path);
-	if (file->path == NULL) {
-		os_error_t err = get_os_error_state();
-		free(file);
-		set_os_error_state(err);
-		return SQFS_ERROR_ALLOC;
-	}
-
-	ret = DuplicateHandle(GetCurrentProcess(), hnd,
-			      GetCurrentProcess(), &file->hnd,
-			      0, FALSE, DUPLICATE_SAME_ACCESS);
-	if (!ret) {
-		os_error_t err = get_os_error_state();
-		free(file->path);
-		free(file);
-		set_os_error_state(err);
-		return SQFS_ERROR_IO;
-	}
-
-	CloseHandle(hnd);
-
-	strm->get_buffered_data = file_get_buffered_data;
-	strm->advance_buffer = file_advance_buffer;
-	strm->get_filename = file_get_filename;
-
-	*out = strm;
-	return 0;
-}
-
-int sqfs_istream_open_file(sqfs_istream_t **out, const char *path,
-			   sqfs_u32 flags)
-{
-	sqfs_file_handle_t hnd;
-	int ret;
-
-	flags |= SQFS_FILE_OPEN_READ_ONLY;
-
-	if (flags & (SQFS_FILE_OPEN_OVERWRITE | SQFS_FILE_OPEN_NO_SPARSE))
-		return SQFS_ERROR_ARG_INVALID;
-
-	ret = sqfs_open_native_file(&hnd, path, flags);
-	if (ret)
-		return ret;
-
-	ret = sqfs_istream_open_handle(out, path, hnd, flags);
-	if (ret) {
-		os_error_t err = get_os_error_state();
-		CloseHandle(hnd);
-		set_os_error_state(err);
-		return ret;
-	}
-
-	return 0;
-}
diff --git a/lib/sqfs/src/win32/ostream.c b/lib/sqfs/src/win32/ostream.c
deleted file mode 100644
index 2f85c29..0000000
--- a/lib/sqfs/src/win32/ostream.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * ostream.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#define SQFS_BUILDING_DLL
-#include "config.h"
-
-#include "sqfs/io.h"
-#include "sqfs/error.h"
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-typedef struct {
-	sqfs_ostream_t base;
-	sqfs_u64 sparse_count;
-	char *path;
-	HANDLE hnd;
-	int flags;
-} file_ostream_t;
-
-static int write_data(file_ostream_t *file, const void *data, size_t size)
-{
-	DWORD diff;
-
-	while (size > 0) {
-		if (!WriteFile(file->hnd, data, size, &diff, NULL))
-			return SQFS_ERROR_IO;
-
-		size -= diff;
-		data = (const char *)data + diff;
-	}
-
-	return 0;
-}
-
-static int realize_sparse(file_ostream_t *file)
-{
-	size_t bufsz, diff;
-	LARGE_INTEGER pos;
-	void *buffer;
-	int ret;
-
-	if (file->sparse_count == 0)
-		return 0;
-
-	if (file->flags & SQFS_FILE_OPEN_NO_SPARSE) {
-		bufsz = file->sparse_count > 1024 ? 1024 : file->sparse_count;
-		buffer = calloc(1, bufsz);
-
-		if (buffer == NULL)
-			return SQFS_ERROR_ALLOC;
-
-		while (file->sparse_count > 0) {
-			diff = file->sparse_count > bufsz ?
-				bufsz : file->sparse_count;
-
-			ret = write_data(file, buffer, diff);
-			if (ret) {
-				os_error_t err = get_os_error_state();
-				free(buffer);
-				set_os_error_state(err);
-				return ret;
-			}
-
-			file->sparse_count -= diff;
-		}
-
-		free(buffer);
-	} else {
-		pos.QuadPart = file->sparse_count;
-
-		if (!SetFilePointerEx(file->hnd, pos, NULL, FILE_CURRENT))
-			return SQFS_ERROR_IO;
-
-		if (!SetEndOfFile(file->hnd))
-			return SQFS_ERROR_IO;
-
-		file->sparse_count = 0;
-	}
-
-	return 0;
-}
-
-static int file_append(sqfs_ostream_t *strm, const void *data, size_t size)
-{
-	file_ostream_t *file = (file_ostream_t *)strm;
-	int ret;
-
-	if (size == 0 || data == NULL) {
-		file->sparse_count += size;
-		return 0;
-	}
-
-	ret = realize_sparse(file);
-	if (ret)
-		return ret;
-
-	return write_data(file, data, size);
-}
-
-static int file_flush(sqfs_ostream_t *strm)
-{
-	file_ostream_t *file = (file_ostream_t *)strm;
-	int ret;
-
-	ret = realize_sparse(file);
-	if (ret)
-		return ret;
-
-	if (!FlushFileBuffers(file->hnd))
-		return SQFS_ERROR_IO;
-
-	return 0;
-}
-
-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(sqfs_ostream_t *strm)
-{
-	return ((file_ostream_t *)strm)->path;
-}
-
-int sqfs_ostream_open_handle(sqfs_ostream_t **out, const char *path,
-			     sqfs_file_handle_t hnd, sqfs_u32 flags)
-{
-	file_ostream_t *file;
-	sqfs_ostream_t *strm;
-	BOOL ret;
-
-	if (flags & ~(SQFS_FILE_OPEN_ALL_FLAGS))
-		return SQFS_ERROR_UNSUPPORTED;
-
-	file = calloc(1, sizeof(*file));
-	strm = (sqfs_ostream_t *)file;
-	if (file == NULL)
-		return SQFS_ERROR_ALLOC;
-
-	sqfs_object_init(file, file_destroy, NULL);
-
-	file->path = strdup(path);
-	if (file->path == NULL) {
-		free(file);
-		return SQFS_ERROR_ALLOC;
-	}
-
-	ret = DuplicateHandle(GetCurrentProcess(), hnd,
-			      GetCurrentProcess(), &file->hnd,
-			      0, FALSE, DUPLICATE_SAME_ACCESS);
-	if (!ret) {
-		os_error_t err = get_os_error_state();
-		free(file->path);
-		free(file);
-		set_os_error_state(err);
-		return SQFS_ERROR_IO;
-	}
-
-	CloseHandle(hnd);
-
-	file->flags = flags;
-	strm->append = file_append;
-	strm->flush = file_flush;
-	strm->get_filename = file_get_filename;
-
-	*out = strm;
-	return 0;
-}
-
-int sqfs_ostream_open_file(sqfs_ostream_t **out, const char *path,
-			   sqfs_u32 flags)
-{
-	sqfs_file_handle_t hnd;
-	int ret;
-
-	*out = NULL;
-	if (flags & SQFS_FILE_OPEN_READ_ONLY)
-		return SQFS_ERROR_ARG_INVALID;
-
-	ret = sqfs_open_native_file(&hnd, path, flags);
-	if (ret)
-		return ret;
-
-	ret = sqfs_ostream_open_handle(out, path, hnd, flags);
-	if (ret) {
-		os_error_t err = get_os_error_state();
-		CloseHandle(hnd);
-		set_os_error_state(err);
-		return SQFS_ERROR_IO;
-	}
-
-	return 0;
-}
-- 
cgit v1.2.3