From 44c81eeffe9c8820b1009a7a5c728782aa5ebf40 Mon Sep 17 00:00:00 2001
From: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Date: Tue, 3 Mar 2020 19:43:54 +0100
Subject: Add a generic copying mechanism to sqfs_object_t

This patch adds a deep-copy callback to sqfs_object_t and removes the
copying mechanism from sqfs_compressor_t. This is also interesting for
other types.

Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
---
 lib/sqfs/win32/io_file.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

(limited to 'lib/sqfs/win32')

diff --git a/lib/sqfs/win32/io_file.c b/lib/sqfs/win32/io_file.c
index c1849a8..836aa37 100644
--- a/lib/sqfs/win32/io_file.c
+++ b/lib/sqfs/win32/io_file.c
@@ -19,6 +19,7 @@
 typedef struct {
 	sqfs_file_t base;
 
+	bool readonly;
 	sqfs_u64 size;
 	HANDLE fd;
 } sqfs_file_stdio_t;
@@ -32,6 +33,35 @@ static void stdio_destroy(sqfs_object_t *base)
 	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;
+	BOOL ret;
+
+	if (!file->readonly) {
+		SetLastError(ERROR_NOT_SUPPORTED);
+		return NULL;
+	}
+
+	copy = calloc(1, sizeof(*copy));
+	if (copy == NULL)
+		return NULL;
+
+	memcpy(copy, file, sizeof(*file));
+
+	ret = DuplicateHandle(GetCurrentProcess(), file->fd,
+			      GetCurrentProcess(), &copy->fd,
+			      0, FALSE, DUPLICATE_SAME_ACCESS);
+
+	if (!ret) {
+		free(copy);
+		return NULL;
+	}
+
+	return (sqfs_object_t *)copy;
+}
+
 static int stdio_read_at(sqfs_file_t *base, sqfs_u64 offset,
 			 void *buffer, size_t size)
 {
@@ -135,9 +165,11 @@ sqfs_file_t *sqfs_open_file(const char *filename, sqfs_u32 flags)
 		return NULL;
 
 	if (flags & SQFS_FILE_OPEN_READ_ONLY) {
+		file->readonly = true;
 		access_flags = GENERIC_READ;
 		creation_mode = OPEN_EXISTING;
 	} else {
+		file->readonly = false;
 		access_flags = GENERIC_READ | GENERIC_WRITE;
 
 		if (flags & SQFS_FILE_OPEN_OVERWRITE) {
@@ -166,5 +198,6 @@ sqfs_file_t *sqfs_open_file(const char *filename, sqfs_u32 flags)
 	base->get_size = stdio_get_size;
 	base->truncate = stdio_truncate;
 	((sqfs_object_t *)base)->destroy = stdio_destroy;
+	((sqfs_object_t *)base)->copy = stdio_copy;
 	return base;
 }
-- 
cgit v1.2.3