Blame SOURCES/0004-libsemanage-move-compressed-file-handling-into-a-sep.patch

e2ef9d
From 7b059d3ca56dbe7003cec921c13be70f9fa1a0f7 Mon Sep 17 00:00:00 2001
e2ef9d
From: Ondrej Mosnacek <omosnace@redhat.com>
e2ef9d
Date: Thu, 3 Feb 2022 17:53:24 +0100
e2ef9d
Subject: [PATCH] libsemanage: move compressed file handling into a separate
e2ef9d
 object
e2ef9d
e2ef9d
In order to reduce exisiting and future code duplication and to avoid
e2ef9d
some unnecessary allocations and copying, factor the compressed file
e2ef9d
utility functions out into a separate C/header file and refactor their
e2ef9d
interface.
e2ef9d
e2ef9d
Note that this change effectively removes the __fsetlocking(3) call from
e2ef9d
semanage_load_files() - I haven't been able to figure out what purpose
e2ef9d
it serves, but it seems pointless...
e2ef9d
e2ef9d
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
e2ef9d
---
e2ef9d
 libsemanage/src/compressed_file.c | 224 +++++++++++++++++++++++++
e2ef9d
 libsemanage/src/compressed_file.h |  78 +++++++++
e2ef9d
 libsemanage/src/direct_api.c      | 263 +++++-------------------------
e2ef9d
 libsemanage/src/direct_api.h      |   4 -
e2ef9d
 libsemanage/src/semanage_store.c  |  52 ++----
e2ef9d
 5 files changed, 354 insertions(+), 267 deletions(-)
e2ef9d
 create mode 100644 libsemanage/src/compressed_file.c
e2ef9d
 create mode 100644 libsemanage/src/compressed_file.h
e2ef9d
e2ef9d
diff --git a/libsemanage/src/compressed_file.c b/libsemanage/src/compressed_file.c
e2ef9d
new file mode 100644
e2ef9d
index 000000000000..5546b83074d5
e2ef9d
--- /dev/null
e2ef9d
+++ b/libsemanage/src/compressed_file.c
e2ef9d
@@ -0,0 +1,224 @@
e2ef9d
+/* Author: Jason Tang	  <jtang@tresys.com>
e2ef9d
+ *         Christopher Ashworth <cashworth@tresys.com>
e2ef9d
+ *         Ondrej Mosnacek <omosnacek@gmail.com>
e2ef9d
+ *
e2ef9d
+ * Copyright (C) 2004-2006 Tresys Technology, LLC
e2ef9d
+ * Copyright (C) 2005-2021 Red Hat, Inc.
e2ef9d
+ *
e2ef9d
+ *  This library is free software; you can redistribute it and/or
e2ef9d
+ *  modify it under the terms of the GNU Lesser General Public
e2ef9d
+ *  License as published by the Free Software Foundation; either
e2ef9d
+ *  version 2.1 of the License, or (at your option) any later version.
e2ef9d
+ *
e2ef9d
+ *  This library is distributed in the hope that it will be useful,
e2ef9d
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
e2ef9d
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
e2ef9d
+ *  Lesser General Public License for more details.
e2ef9d
+ *
e2ef9d
+ *  You should have received a copy of the GNU Lesser General Public
e2ef9d
+ *  License along with this library; if not, write to the Free Software
e2ef9d
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
e2ef9d
+ */
e2ef9d
+
e2ef9d
+#include <stdlib.h>
e2ef9d
+#include <string.h>
e2ef9d
+#include <stdint.h>
e2ef9d
+
e2ef9d
+#include <unistd.h>
e2ef9d
+#include <fcntl.h>
e2ef9d
+
e2ef9d
+#include <bzlib.h>
e2ef9d
+
e2ef9d
+#include "compressed_file.h"
e2ef9d
+
e2ef9d
+#include "debug.h"
e2ef9d
+
e2ef9d
+#define BZ2_MAGICSTR "BZh"
e2ef9d
+#define BZ2_MAGICLEN (sizeof(BZ2_MAGICSTR)-1)
e2ef9d
+
e2ef9d
+/* bzip() a data to a file, returning the total number of compressed bytes
e2ef9d
+ * in the file.  Returns -1 if file could not be compressed. */
e2ef9d
+static int bzip(semanage_handle_t *sh, const char *filename, void *data,
e2ef9d
+		size_t num_bytes)
e2ef9d
+{
e2ef9d
+	BZFILE* b;
e2ef9d
+	size_t  size = 1<<16;
e2ef9d
+	int     bzerror;
e2ef9d
+	size_t  total = 0;
e2ef9d
+	size_t len = 0;
e2ef9d
+	FILE *f;
e2ef9d
+
e2ef9d
+	if ((f = fopen(filename, "wb")) == NULL) {
e2ef9d
+		return -1;
e2ef9d
+	}
e2ef9d
+
e2ef9d
+	if (!sh->conf->bzip_blocksize) {
e2ef9d
+		if (fwrite(data, 1, num_bytes, f) < num_bytes) {
e2ef9d
+			fclose(f);
e2ef9d
+			return -1;
e2ef9d
+		}
e2ef9d
+		fclose(f);
e2ef9d
+		return 0;
e2ef9d
+	}
e2ef9d
+
e2ef9d
+	b = BZ2_bzWriteOpen( &bzerror, f, sh->conf->bzip_blocksize, 0, 0);
e2ef9d
+	if (bzerror != BZ_OK) {
e2ef9d
+		BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
e2ef9d
+		fclose(f);
e2ef9d
+		return -1;
e2ef9d
+	}
e2ef9d
+
e2ef9d
+	while ( num_bytes > total ) {
e2ef9d
+		if (num_bytes - total > size) {
e2ef9d
+			len = size;
e2ef9d
+		} else {
e2ef9d
+			len = num_bytes - total;
e2ef9d
+		}
e2ef9d
+		BZ2_bzWrite ( &bzerror, b, (uint8_t *)data + total, len );
e2ef9d
+		if (bzerror == BZ_IO_ERROR) {
e2ef9d
+			BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
e2ef9d
+			fclose(f);
e2ef9d
+			return -1;
e2ef9d
+		}
e2ef9d
+		total += len;
e2ef9d
+	}
e2ef9d
+
e2ef9d
+	BZ2_bzWriteClose ( &bzerror, b, 0, 0, 0 );
e2ef9d
+	fclose(f);
e2ef9d
+	if (bzerror == BZ_IO_ERROR) {
e2ef9d
+		return -1;
e2ef9d
+	}
e2ef9d
+	return 0;
e2ef9d
+}
e2ef9d
+
e2ef9d
+/* bunzip() a file to '*data', returning the total number of uncompressed bytes
e2ef9d
+ * in the file.  Returns -1 if file could not be decompressed. */
e2ef9d
+static ssize_t bunzip(semanage_handle_t *sh, FILE *f, void **data)
e2ef9d
+{
e2ef9d
+	BZFILE*  b = NULL;
e2ef9d
+	size_t   nBuf;
e2ef9d
+	uint8_t* buf = NULL;
e2ef9d
+	size_t   size = 1<<18;
e2ef9d
+	size_t   bufsize = size;
e2ef9d
+	int      bzerror;
e2ef9d
+	size_t   total = 0;
e2ef9d
+	uint8_t* uncompress = NULL;
e2ef9d
+	uint8_t* tmpalloc = NULL;
e2ef9d
+	int      ret = -1;
e2ef9d
+
e2ef9d
+	buf = malloc(bufsize);
e2ef9d
+	if (buf == NULL) {
e2ef9d
+		ERR(sh, "Failure allocating memory.");
e2ef9d
+		goto exit;
e2ef9d
+	}
e2ef9d
+
e2ef9d
+	/* Check if the file is bzipped */
e2ef9d
+	bzerror = fread(buf, 1, BZ2_MAGICLEN, f);
e2ef9d
+	rewind(f);
e2ef9d
+	if ((bzerror != BZ2_MAGICLEN) || memcmp(buf, BZ2_MAGICSTR, BZ2_MAGICLEN)) {
e2ef9d
+		goto exit;
e2ef9d
+	}
e2ef9d
+
e2ef9d
+	b = BZ2_bzReadOpen ( &bzerror, f, 0, sh->conf->bzip_small, NULL, 0 );
e2ef9d
+	if ( bzerror != BZ_OK ) {
e2ef9d
+		ERR(sh, "Failure opening bz2 archive.");
e2ef9d
+		goto exit;
e2ef9d
+	}
e2ef9d
+
e2ef9d
+	uncompress = malloc(size);
e2ef9d
+	if (uncompress == NULL) {
e2ef9d
+		ERR(sh, "Failure allocating memory.");
e2ef9d
+		goto exit;
e2ef9d
+	}
e2ef9d
+
e2ef9d
+	while ( bzerror == BZ_OK) {
e2ef9d
+		nBuf = BZ2_bzRead ( &bzerror, b, buf, bufsize);
e2ef9d
+		if (( bzerror == BZ_OK ) || ( bzerror == BZ_STREAM_END )) {
e2ef9d
+			if (total + nBuf > size) {
e2ef9d
+				size *= 2;
e2ef9d
+				tmpalloc = realloc(uncompress, size);
e2ef9d
+				if (tmpalloc == NULL) {
e2ef9d
+					ERR(sh, "Failure allocating memory.");
e2ef9d
+					goto exit;
e2ef9d
+				}
e2ef9d
+				uncompress = tmpalloc;
e2ef9d
+			}
e2ef9d
+			memcpy(&uncompress[total], buf, nBuf);
e2ef9d
+			total += nBuf;
e2ef9d
+		}
e2ef9d
+	}
e2ef9d
+	if ( bzerror != BZ_STREAM_END ) {
e2ef9d
+		ERR(sh, "Failure reading bz2 archive.");
e2ef9d
+		goto exit;
e2ef9d
+	}
e2ef9d
+
e2ef9d
+	ret = total;
e2ef9d
+	*data = uncompress;
e2ef9d
+
e2ef9d
+exit:
e2ef9d
+	BZ2_bzReadClose ( &bzerror, b );
e2ef9d
+	free(buf);
e2ef9d
+	if ( ret < 0 ) {
e2ef9d
+		free(uncompress);
e2ef9d
+	}
e2ef9d
+	return ret;
e2ef9d
+}
e2ef9d
+
e2ef9d
+int map_compressed_file(semanage_handle_t *sh, const char *path,
e2ef9d
+			struct file_contents *contents)
e2ef9d
+{
e2ef9d
+	ssize_t size = -1;
e2ef9d
+	void *uncompress;
e2ef9d
+	int ret = 0, fd = -1;
e2ef9d
+	FILE *file = NULL;
e2ef9d
+
e2ef9d
+	fd = open(path, O_RDONLY);
e2ef9d
+	if (fd == -1) {
e2ef9d
+		ERR(sh, "Unable to open %s\n", path);
e2ef9d
+		return -1;
e2ef9d
+	}
e2ef9d
+
e2ef9d
+	file = fdopen(fd, "r");
e2ef9d
+	if (file == NULL) {
e2ef9d
+		ERR(sh, "Unable to open %s\n", path);
e2ef9d
+		close(fd);
e2ef9d
+		return -1;
e2ef9d
+	}
e2ef9d
+
e2ef9d
+	if ((size = bunzip(sh, file, &uncompress)) >= 0) {
e2ef9d
+		contents->data = uncompress;
e2ef9d
+		contents->len = size;
e2ef9d
+		contents->compressed = 1;
e2ef9d
+	} else {
e2ef9d
+		struct stat sb;
e2ef9d
+		if (fstat(fd, &sb) == -1 ||
e2ef9d
+		    (uncompress = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) ==
e2ef9d
+		    MAP_FAILED) {
e2ef9d
+			ret = -1;
e2ef9d
+		} else {
e2ef9d
+			contents->data = uncompress;
e2ef9d
+			contents->len = sb.st_size;
e2ef9d
+			contents->compressed = 0;
e2ef9d
+		}
e2ef9d
+	}
e2ef9d
+	fclose(file);
e2ef9d
+	return ret;
e2ef9d
+}
e2ef9d
+
e2ef9d
+void unmap_compressed_file(struct file_contents *contents)
e2ef9d
+{
e2ef9d
+	if (!contents->data)
e2ef9d
+		return;
e2ef9d
+
e2ef9d
+	if (contents->compressed) {
e2ef9d
+		free(contents->data);
e2ef9d
+	} else {
e2ef9d
+		munmap(contents->data, contents->len);
e2ef9d
+	}
e2ef9d
+}
e2ef9d
+
e2ef9d
+int write_compressed_file(semanage_handle_t *sh, const char *path,
e2ef9d
+			  void *data, size_t len)
e2ef9d
+{
e2ef9d
+	return bzip(sh, path, data, len);
e2ef9d
+}
e2ef9d
diff --git a/libsemanage/src/compressed_file.h b/libsemanage/src/compressed_file.h
e2ef9d
new file mode 100644
e2ef9d
index 000000000000..96cfb4b6304a
e2ef9d
--- /dev/null
e2ef9d
+++ b/libsemanage/src/compressed_file.h
e2ef9d
@@ -0,0 +1,78 @@
e2ef9d
+/* Author: Jason Tang	  <jtang@tresys.com>
e2ef9d
+ *         Christopher Ashworth <cashworth@tresys.com>
e2ef9d
+ *         Ondrej Mosnacek <omosnacek@gmail.com>
e2ef9d
+ *
e2ef9d
+ * Copyright (C) 2004-2006 Tresys Technology, LLC
e2ef9d
+ * Copyright (C) 2005-2021 Red Hat, Inc.
e2ef9d
+ *
e2ef9d
+ *  This library is free software; you can redistribute it and/or
e2ef9d
+ *  modify it under the terms of the GNU Lesser General Public
e2ef9d
+ *  License as published by the Free Software Foundation; either
e2ef9d
+ *  version 2.1 of the License, or (at your option) any later version.
e2ef9d
+ *
e2ef9d
+ *  This library is distributed in the hope that it will be useful,
e2ef9d
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
e2ef9d
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
e2ef9d
+ *  Lesser General Public License for more details.
e2ef9d
+ *
e2ef9d
+ *  You should have received a copy of the GNU Lesser General Public
e2ef9d
+ *  License along with this library; if not, write to the Free Software
e2ef9d
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
e2ef9d
+ */
e2ef9d
+
e2ef9d
+#ifndef _SEMANAGE_CIL_FILE_H_
e2ef9d
+#define _SEMANAGE_CIL_FILE_H_
e2ef9d
+
e2ef9d
+#include <sys/mman.h>
e2ef9d
+#include <sys/types.h>
e2ef9d
+
e2ef9d
+#include "handle.h"
e2ef9d
+
e2ef9d
+struct file_contents {
e2ef9d
+	void *data; /** file contents (uncompressed) */
e2ef9d
+	size_t len; /** length of contents */
e2ef9d
+	int compressed; /** whether file was compressed */
e2ef9d
+};
e2ef9d
+
e2ef9d
+/**
e2ef9d
+ * Map/read a possibly-compressed file into memory.
e2ef9d
+ *
e2ef9d
+ * If the file is bzip compressed map_file will uncompress the file into
e2ef9d
+ * @p contents. The caller is responsible for calling
e2ef9d
+ * @ref unmap_compressed_file on @p contents on success.
e2ef9d
+ *
e2ef9d
+ * @param sh        semanage handle
e2ef9d
+ * @param path      path to the file
e2ef9d
+ * @param contents  pointer to struct file_contents, which will be
e2ef9d
+ *   populated with data pointer, size, and an indication whether
e2ef9d
+ *   the file was compressed or not
e2ef9d
+ *
e2ef9d
+ * @return 0 on success, -1 otherwise.
e2ef9d
+ */
e2ef9d
+int map_compressed_file(semanage_handle_t *sh, const char *path,
e2ef9d
+			struct file_contents *contents);
e2ef9d
+
e2ef9d
+/**
e2ef9d
+ * Destroy a previously mapped possibly-compressed file.
e2ef9d
+ *
e2ef9d
+ * If all fields of @p contents are zero/NULL, the function is
e2ef9d
+ * guaranteed to do nothing.
e2ef9d
+ *
e2ef9d
+ * @param contents  pointer to struct file_contents to destroy
e2ef9d
+ */
e2ef9d
+void unmap_compressed_file(struct file_contents *contents);
e2ef9d
+
e2ef9d
+/**
e2ef9d
+ * Write bytes into a file, using compression if configured.
e2ef9d
+ *
e2ef9d
+ * @param sh    semanage handle
e2ef9d
+ * @param path  path to the file
e2ef9d
+ * @param data  pointer to the data
e2ef9d
+ * @param len   length of the data
e2ef9d
+ *
e2ef9d
+ * @return 0 on success, -1 otherwise.
e2ef9d
+ */
e2ef9d
+int write_compressed_file(semanage_handle_t *sh, const char *path,
e2ef9d
+			  void *data, size_t len);
e2ef9d
+
e2ef9d
+#endif
e2ef9d
diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
e2ef9d
index b7a3e0f17cc1..aa2bfcf35016 100644
e2ef9d
--- a/libsemanage/src/direct_api.c
e2ef9d
+++ b/libsemanage/src/direct_api.c
e2ef9d
@@ -50,6 +50,7 @@
e2ef9d
 
e2ef9d
 #include "debug.h"
e2ef9d
 #include "handle.h"
e2ef9d
+#include "compressed_file.h"
e2ef9d
 #include "modules.h"
e2ef9d
 #include "direct_api.h"
e2ef9d
 #include "semanage_store.h"
e2ef9d
@@ -446,194 +447,6 @@ static int parse_module_headers(semanage_handle_t * sh, char *module_data,
e2ef9d
        return 0;
e2ef9d
 }
e2ef9d
 
e2ef9d
-#include <stdlib.h>
e2ef9d
-#include <bzlib.h>
e2ef9d
-#include <string.h>
e2ef9d
-#include <sys/sendfile.h>
e2ef9d
-
e2ef9d
-/* bzip() a data to a file, returning the total number of compressed bytes
e2ef9d
- * in the file.  Returns -1 if file could not be compressed. */
e2ef9d
-static ssize_t bzip(semanage_handle_t *sh, const char *filename, char *data,
e2ef9d
-			size_t num_bytes)
e2ef9d
-{
e2ef9d
-	BZFILE* b;
e2ef9d
-	size_t  size = 1<<16;
e2ef9d
-	int     bzerror;
e2ef9d
-	size_t  total = 0;
e2ef9d
-	size_t len = 0;
e2ef9d
-	FILE *f;
e2ef9d
-
e2ef9d
-	if ((f = fopen(filename, "wb")) == NULL) {
e2ef9d
-		return -1;
e2ef9d
-	}
e2ef9d
-
e2ef9d
-	if (!sh->conf->bzip_blocksize) {
e2ef9d
-		if (fwrite(data, 1, num_bytes, f) < num_bytes) {
e2ef9d
-			fclose(f);
e2ef9d
-			return -1;
e2ef9d
-		}
e2ef9d
-		fclose(f);
e2ef9d
-		return num_bytes;
e2ef9d
-	}
e2ef9d
-
e2ef9d
-	b = BZ2_bzWriteOpen( &bzerror, f, sh->conf->bzip_blocksize, 0, 0);
e2ef9d
-	if (bzerror != BZ_OK) {
e2ef9d
-		BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
e2ef9d
-		return -1;
e2ef9d
-	}
e2ef9d
-	
e2ef9d
-	while ( num_bytes > total ) {
e2ef9d
-		if (num_bytes - total > size) {
e2ef9d
-			len = size;
e2ef9d
-		} else {
e2ef9d
-			len = num_bytes - total;
e2ef9d
-		}
e2ef9d
-		BZ2_bzWrite ( &bzerror, b, &data[total], len );
e2ef9d
-		if (bzerror == BZ_IO_ERROR) { 
e2ef9d
-			BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
e2ef9d
-			return -1;
e2ef9d
-		}
e2ef9d
-		total += len;
e2ef9d
-	}
e2ef9d
-
e2ef9d
-	BZ2_bzWriteClose ( &bzerror, b, 0, 0, 0 );
e2ef9d
-	fclose(f);
e2ef9d
-	if (bzerror == BZ_IO_ERROR) {
e2ef9d
-		return -1;
e2ef9d
-	}
e2ef9d
-	return total;
e2ef9d
-}
e2ef9d
-
e2ef9d
-#define BZ2_MAGICSTR "BZh"
e2ef9d
-#define BZ2_MAGICLEN (sizeof(BZ2_MAGICSTR)-1)
e2ef9d
-
e2ef9d
-/* bunzip() a file to '*data', returning the total number of uncompressed bytes
e2ef9d
- * in the file.  Returns -1 if file could not be decompressed. */
e2ef9d
-ssize_t bunzip(semanage_handle_t *sh, FILE *f, char **data)
e2ef9d
-{
e2ef9d
-	BZFILE* b = NULL;
e2ef9d
-	size_t  nBuf;
e2ef9d
-	char*   buf = NULL;
e2ef9d
-	size_t  size = 1<<18;
e2ef9d
-	size_t  bufsize = size;
e2ef9d
-	int     bzerror;
e2ef9d
-	size_t  total = 0;
e2ef9d
-	char*   uncompress = NULL;
e2ef9d
-	char*   tmpalloc = NULL;
e2ef9d
-	int     ret = -1;
e2ef9d
-
e2ef9d
-	buf = malloc(bufsize);
e2ef9d
-	if (buf == NULL) {
e2ef9d
-		ERR(sh, "Failure allocating memory.");
e2ef9d
-		goto exit;
e2ef9d
-	}
e2ef9d
-
e2ef9d
-	/* Check if the file is bzipped */
e2ef9d
-	bzerror = fread(buf, 1, BZ2_MAGICLEN, f);
e2ef9d
-	rewind(f);
e2ef9d
-	if ((bzerror != BZ2_MAGICLEN) || memcmp(buf, BZ2_MAGICSTR, BZ2_MAGICLEN)) {
e2ef9d
-		goto exit;
e2ef9d
-	}
e2ef9d
-
e2ef9d
-	b = BZ2_bzReadOpen ( &bzerror, f, 0, sh->conf->bzip_small, NULL, 0 );
e2ef9d
-	if ( bzerror != BZ_OK ) {
e2ef9d
-		ERR(sh, "Failure opening bz2 archive.");
e2ef9d
-		goto exit;
e2ef9d
-	}
e2ef9d
-
e2ef9d
-	uncompress = malloc(size);
e2ef9d
-	if (uncompress == NULL) {
e2ef9d
-		ERR(sh, "Failure allocating memory.");
e2ef9d
-		goto exit;
e2ef9d
-	}
e2ef9d
-
e2ef9d
-	while ( bzerror == BZ_OK) {
e2ef9d
-		nBuf = BZ2_bzRead ( &bzerror, b, buf, bufsize);
e2ef9d
-		if (( bzerror == BZ_OK ) || ( bzerror == BZ_STREAM_END )) {
e2ef9d
-			if (total + nBuf > size) {
e2ef9d
-				size *= 2;
e2ef9d
-				tmpalloc = realloc(uncompress, size);
e2ef9d
-				if (tmpalloc == NULL) {
e2ef9d
-					ERR(sh, "Failure allocating memory.");
e2ef9d
-					goto exit;
e2ef9d
-				}
e2ef9d
-				uncompress = tmpalloc;
e2ef9d
-			}
e2ef9d
-			memcpy(&uncompress[total], buf, nBuf);
e2ef9d
-			total += nBuf;
e2ef9d
-		}
e2ef9d
-	}
e2ef9d
-	if ( bzerror != BZ_STREAM_END ) {
e2ef9d
-		ERR(sh, "Failure reading bz2 archive.");
e2ef9d
-		goto exit;
e2ef9d
-	}
e2ef9d
-
e2ef9d
-	ret = total;
e2ef9d
-	*data = uncompress;
e2ef9d
-
e2ef9d
-exit:
e2ef9d
-	BZ2_bzReadClose ( &bzerror, b );
e2ef9d
-	free(buf);
e2ef9d
-	if ( ret < 0 ) {
e2ef9d
-		free(uncompress);
e2ef9d
-	}
e2ef9d
-	return ret;
e2ef9d
-}
e2ef9d
-
e2ef9d
-/* mmap() a file to '*data',
e2ef9d
- *  If the file is bzip compressed map_file will uncompress 
e2ef9d
- * the file into '*data'.
e2ef9d
- * Returns the total number of bytes in memory .
e2ef9d
- * Returns -1 if file could not be opened or mapped. */
e2ef9d
-static ssize_t map_file(semanage_handle_t *sh, const char *path, char **data,
e2ef9d
-			int *compressed)
e2ef9d
-{
e2ef9d
-	ssize_t size = -1;
e2ef9d
-	char *uncompress;
e2ef9d
-	int fd = -1;
e2ef9d
-	FILE *file = NULL;
e2ef9d
-
e2ef9d
-	fd = open(path, O_RDONLY);
e2ef9d
-	if (fd == -1) {
e2ef9d
-		ERR(sh, "Unable to open %s\n", path);
e2ef9d
-		return -1;
e2ef9d
-	}
e2ef9d
-
e2ef9d
-	file = fdopen(fd, "r");
e2ef9d
-	if (file == NULL) {
e2ef9d
-		ERR(sh, "Unable to open %s\n", path);
e2ef9d
-		close(fd);
e2ef9d
-		return -1;
e2ef9d
-	}
e2ef9d
-
e2ef9d
-	if ((size = bunzip(sh, file, &uncompress)) > 0) {
e2ef9d
-		*data = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
e2ef9d
-		if (*data == MAP_FAILED) {
e2ef9d
-			free(uncompress);
e2ef9d
-			fclose(file);
e2ef9d
-			return -1;
e2ef9d
-		} else {
e2ef9d
-			memcpy(*data, uncompress, size);
e2ef9d
-		}
e2ef9d
-		free(uncompress);
e2ef9d
-		*compressed = 1;
e2ef9d
-	} else {
e2ef9d
-		struct stat sb;
e2ef9d
-		if (fstat(fd, &sb) == -1 ||
e2ef9d
-		    (*data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) ==
e2ef9d
-		    MAP_FAILED) {
e2ef9d
-			size = -1;
e2ef9d
-		} else {
e2ef9d
-			size = sb.st_size;
e2ef9d
-		}
e2ef9d
-		*compressed = 0;
e2ef9d
-	} 
e2ef9d
-
e2ef9d
-	fclose(file);
e2ef9d
-
e2ef9d
-	return size;
e2ef9d
-}
e2ef9d
-
e2ef9d
 /* Writes a block of data to a file.  Returns 0 on success, -1 on
e2ef9d
  * error. */
e2ef9d
 static int write_file(semanage_handle_t * sh,
e2ef9d
@@ -1045,15 +858,12 @@ static int semanage_compile_module(semanage_handle_t *sh,
e2ef9d
 	char *compiler_path = NULL;
e2ef9d
 	char *cil_data = NULL;
e2ef9d
 	char *err_data = NULL;
e2ef9d
-	char *hll_data = NULL;
e2ef9d
 	char *start = NULL;
e2ef9d
 	char *end = NULL;
e2ef9d
-	ssize_t hll_data_len = 0;
e2ef9d
-	ssize_t bzip_status;
e2ef9d
 	int status = 0;
e2ef9d
-	int compressed;
e2ef9d
 	size_t cil_data_len = 0;
e2ef9d
 	size_t err_data_len = 0;
e2ef9d
+	struct file_contents hll_contents = {};
e2ef9d
 
e2ef9d
 	if (!strcasecmp(modinfo->lang_ext, "cil")) {
e2ef9d
 		goto cleanup;
e2ef9d
@@ -1084,13 +894,15 @@ static int semanage_compile_module(semanage_handle_t *sh,
e2ef9d
 		goto cleanup;
e2ef9d
 	}
e2ef9d
 
e2ef9d
-	if ((hll_data_len = map_file(sh, hll_path, &hll_data, &compressed)) <= 0) {
e2ef9d
+	status = map_compressed_file(sh, hll_path, &hll_contents);
e2ef9d
+	if (status < 0) {
e2ef9d
 		ERR(sh, "Unable to read file %s\n", hll_path);
e2ef9d
-		status = -1;
e2ef9d
 		goto cleanup;
e2ef9d
 	}
e2ef9d
 
e2ef9d
-	status = semanage_pipe_data(sh, compiler_path, hll_data, (size_t)hll_data_len, &cil_data, &cil_data_len, &err_data, &err_data_len);
e2ef9d
+	status = semanage_pipe_data(sh, compiler_path, hll_contents.data,
e2ef9d
+				    hll_contents.len, &cil_data, &cil_data_len,
e2ef9d
+				    &err_data, &err_data_len);
e2ef9d
 	if (err_data_len > 0) {
e2ef9d
 		for (start = end = err_data; end < err_data + err_data_len; end++) {
e2ef9d
 			if (*end == '\n') {
e2ef9d
@@ -1110,10 +922,9 @@ static int semanage_compile_module(semanage_handle_t *sh,
e2ef9d
 		goto cleanup;
e2ef9d
 	}
e2ef9d
 
e2ef9d
-	bzip_status = bzip(sh, cil_path, cil_data, cil_data_len);
e2ef9d
-	if (bzip_status == -1) {
e2ef9d
-		ERR(sh, "Failed to bzip %s\n", cil_path);
e2ef9d
-		status = -1;
e2ef9d
+	status = write_compressed_file(sh, cil_path, cil_data, cil_data_len);
e2ef9d
+	if (status == -1) {
e2ef9d
+		ERR(sh, "Failed to write %s\n", cil_path);
e2ef9d
 		goto cleanup;
e2ef9d
 	}
e2ef9d
 
e2ef9d
@@ -1131,9 +942,7 @@ static int semanage_compile_module(semanage_handle_t *sh,
e2ef9d
 	}
e2ef9d
 
e2ef9d
 cleanup:
e2ef9d
-	if (hll_data_len > 0) {
e2ef9d
-		munmap(hll_data, hll_data_len);
e2ef9d
-	}
e2ef9d
+	unmap_compressed_file(&hll_contents);
e2ef9d
 	free(cil_data);
e2ef9d
 	free(err_data);
e2ef9d
 	free(compiler_path);
e2ef9d
@@ -1756,19 +1565,17 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
e2ef9d
 {
e2ef9d
 
e2ef9d
 	int retval = -1;
e2ef9d
-	char *data = NULL;
e2ef9d
-	ssize_t data_len = 0;
e2ef9d
-	int compressed = 0;
e2ef9d
 	char *path = NULL;
e2ef9d
 	char *filename;
e2ef9d
 	char *lang_ext = NULL;
e2ef9d
 	char *module_name = NULL;
e2ef9d
 	char *separator;
e2ef9d
 	char *version = NULL;
e2ef9d
+	struct file_contents contents = {};
e2ef9d
 
e2ef9d
-	if ((data_len = map_file(sh, install_filename, &data, &compressed)) <= 0) {
e2ef9d
+	retval = map_compressed_file(sh, install_filename, &contents);
e2ef9d
+	if (retval < 0) {
e2ef9d
 		ERR(sh, "Unable to read file %s\n", install_filename);
e2ef9d
-		retval = -1;
e2ef9d
 		goto cleanup;
e2ef9d
 	}
e2ef9d
 
e2ef9d
@@ -1781,7 +1588,7 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
e2ef9d
 
e2ef9d
 	filename = basename(path);
e2ef9d
 
e2ef9d
-	if (compressed) {
e2ef9d
+	if (contents.compressed) {
e2ef9d
 		separator = strrchr(filename, '.');
e2ef9d
 		if (separator == NULL) {
e2ef9d
 			ERR(sh, "Compressed module does not have a valid extension.");
e2ef9d
@@ -1805,7 +1612,8 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
e2ef9d
 	}
e2ef9d
 
e2ef9d
 	if (strcmp(lang_ext, "pp") == 0) {
e2ef9d
-		retval = parse_module_headers(sh, data, data_len, &module_name, &version);
e2ef9d
+		retval = parse_module_headers(sh, contents.data, contents.len,
e2ef9d
+					      &module_name, &version);
e2ef9d
 		free(version);
e2ef9d
 		if (retval != 0)
e2ef9d
 			goto cleanup;
e2ef9d
@@ -1822,10 +1630,11 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
e2ef9d
 		fprintf(stderr, "Warning: SELinux userspace will refer to the module from %s as %s rather than %s\n", install_filename, module_name, filename);
e2ef9d
 	}
e2ef9d
 
e2ef9d
-	retval = semanage_direct_install(sh, data, data_len, module_name, lang_ext);
e2ef9d
+	retval = semanage_direct_install(sh, contents.data, contents.len,
e2ef9d
+					 module_name, lang_ext);
e2ef9d
 
e2ef9d
 cleanup:
e2ef9d
-	if (data_len > 0) munmap(data, data_len);
e2ef9d
+	unmap_compressed_file(&contents);
e2ef9d
 	free(module_name);
e2ef9d
 	free(path);
e2ef9d
 
e2ef9d
@@ -1844,10 +1653,8 @@ static int semanage_direct_extract(semanage_handle_t * sh,
e2ef9d
 	enum semanage_module_path_type file_type;
e2ef9d
 	int rc = -1;
e2ef9d
 	semanage_module_info_t *_modinfo = NULL;
e2ef9d
-	ssize_t _data_len;
e2ef9d
-	char *_data;
e2ef9d
-	int compressed;
e2ef9d
 	struct stat sb;
e2ef9d
+	struct file_contents contents = {};
e2ef9d
 
e2ef9d
 	/* get path of module */
e2ef9d
 	rc = semanage_module_get_path(
e2ef9d
@@ -1903,19 +1710,33 @@ static int semanage_direct_extract(semanage_handle_t * sh,
e2ef9d
 		}
e2ef9d
 	}
e2ef9d
 
e2ef9d
-	_data_len = map_file(sh, input_file, &_data, &compressed);
e2ef9d
-	if (_data_len <= 0) {
e2ef9d
+	rc = map_compressed_file(sh, input_file, &contents);
e2ef9d
+	if (rc < 0) {
e2ef9d
 		ERR(sh, "Error mapping file: %s", input_file);
e2ef9d
-		rc = -1;
e2ef9d
 		goto cleanup;
e2ef9d
 	}
e2ef9d
 
e2ef9d
+	/* The API promises an mmap'ed pointer */
e2ef9d
+	if (contents.compressed) {
e2ef9d
+		*mapped_data = mmap(NULL, contents.len, PROT_READ|PROT_WRITE,
e2ef9d
+				    MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
e2ef9d
+		if (*mapped_data == MAP_FAILED) {
e2ef9d
+			ERR(sh, "Unable to map memory");
e2ef9d
+			rc = -1;
e2ef9d
+			goto cleanup;
e2ef9d
+		}
e2ef9d
+		memcpy(*mapped_data, contents.data, contents.len);
e2ef9d
+		free(contents.data);
e2ef9d
+	} else {
e2ef9d
+		*mapped_data = contents.data;
e2ef9d
+	}
e2ef9d
+
e2ef9d
 	*modinfo = _modinfo;
e2ef9d
-	*data_len = (size_t)_data_len;
e2ef9d
-	*mapped_data = _data;
e2ef9d
+	*data_len = contents.len;
e2ef9d
 
e2ef9d
 cleanup:
e2ef9d
 	if (rc != 0) {
e2ef9d
+		unmap_compressed_file(&contents);
e2ef9d
 		semanage_module_info_destroy(sh, _modinfo);
e2ef9d
 		free(_modinfo);
e2ef9d
 	}
e2ef9d
@@ -2864,8 +2685,8 @@ static int semanage_direct_install_info(semanage_handle_t *sh,
e2ef9d
 		goto cleanup;
e2ef9d
 	}
e2ef9d
 
e2ef9d
-	ret = bzip(sh, path, data, data_len);
e2ef9d
-	if (ret <= 0) {
e2ef9d
+	ret = write_compressed_file(sh, path, data, data_len);
e2ef9d
+	if (ret < 0) {
e2ef9d
 		ERR(sh, "Error while writing to %s.", path);
e2ef9d
 		status = -3;
e2ef9d
 		goto cleanup;
e2ef9d
diff --git a/libsemanage/src/direct_api.h b/libsemanage/src/direct_api.h
e2ef9d
index e56107b27573..ffd428eb82ba 100644
e2ef9d
--- a/libsemanage/src/direct_api.h
e2ef9d
+++ b/libsemanage/src/direct_api.h
e2ef9d
@@ -39,8 +39,4 @@ int semanage_direct_access_check(struct semanage_handle *sh);
e2ef9d
 
e2ef9d
 int semanage_direct_mls_enabled(struct semanage_handle *sh);
e2ef9d
 
e2ef9d
-#include <stdio.h>
e2ef9d
-#include <unistd.h>
e2ef9d
-ssize_t bunzip(struct semanage_handle *sh, FILE *f, char **data);
e2ef9d
-
e2ef9d
 #endif
e2ef9d
diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
e2ef9d
index c6a736fe2d26..633ee73165fb 100644
e2ef9d
--- a/libsemanage/src/semanage_store.c
e2ef9d
+++ b/libsemanage/src/semanage_store.c
e2ef9d
@@ -59,6 +59,7 @@ typedef struct dbase_policydb dbase_t;
e2ef9d
 
e2ef9d
 #include "debug.h"
e2ef9d
 #include "utilities.h"
e2ef9d
+#include "compressed_file.h"
e2ef9d
 
e2ef9d
 #define SEMANAGE_CONF_FILE "semanage.conf"
e2ef9d
 /* relative path names to enum semanage_paths to special files and
e2ef9d
@@ -2054,60 +2055,27 @@ int semanage_direct_get_serial(semanage_handle_t * sh)
e2ef9d
 
e2ef9d
 int semanage_load_files(semanage_handle_t * sh, cil_db_t *cildb, char **filenames, int numfiles)
e2ef9d
 {
e2ef9d
-	int retval = 0;
e2ef9d
-	FILE *fp;
e2ef9d
-	ssize_t size;
e2ef9d
-	char *data = NULL;
e2ef9d
+	int i, retval = 0;
e2ef9d
 	char *filename;
e2ef9d
-	int i;
e2ef9d
+	struct file_contents contents = {};
e2ef9d
 
e2ef9d
 	for (i = 0; i < numfiles; i++) {
e2ef9d
 		filename = filenames[i];
e2ef9d
 
e2ef9d
-		if ((fp = fopen(filename, "rb")) == NULL) {
e2ef9d
-			ERR(sh, "Could not open module file %s for reading.", filename);
e2ef9d
-			goto cleanup;
e2ef9d
-		}
e2ef9d
-
e2ef9d
-		if ((size = bunzip(sh, fp, &data)) <= 0) {
e2ef9d
-			rewind(fp);
e2ef9d
-			__fsetlocking(fp, FSETLOCKING_BYCALLER);
e2ef9d
-
e2ef9d
-			if (fseek(fp, 0, SEEK_END) != 0) {
e2ef9d
-				ERR(sh, "Failed to determine size of file %s.", filename);
e2ef9d
-				goto cleanup;
e2ef9d
-			}
e2ef9d
-			size = ftell(fp);
e2ef9d
-			rewind(fp);
e2ef9d
-
e2ef9d
-			data = malloc(size);
e2ef9d
-			if (fread(data, size, 1, fp) != 1) {
e2ef9d
-				ERR(sh, "Failed to read file %s.", filename);
e2ef9d
-				goto cleanup;
e2ef9d
-			}
e2ef9d
-		}
e2ef9d
+		retval = map_compressed_file(sh, filename, &contents);
e2ef9d
+		if (retval < 0)
e2ef9d
+			return -1;
e2ef9d
 
e2ef9d
-		fclose(fp);
e2ef9d
-		fp = NULL;
e2ef9d
+		retval = cil_add_file(cildb, filename, contents.data, contents.len);
e2ef9d
+		unmap_compressed_file(&contents);
e2ef9d
 
e2ef9d
-		retval = cil_add_file(cildb, filename, data, size);
e2ef9d
 		if (retval != SEPOL_OK) {
e2ef9d
 			ERR(sh, "Error while reading from file %s.", filename);
e2ef9d
-			goto cleanup;
e2ef9d
+			return -1;
e2ef9d
 		}
e2ef9d
-	
e2ef9d
-		free(data);
e2ef9d
-		data = NULL;
e2ef9d
 	}
e2ef9d
 
e2ef9d
-	return retval;
e2ef9d
-
e2ef9d
-      cleanup:
e2ef9d
-	if (fp != NULL) {
e2ef9d
-		fclose(fp);
e2ef9d
-	}
e2ef9d
-	free(data);
e2ef9d
-	return -1;
e2ef9d
+	return 0;
e2ef9d
 }
e2ef9d
 
e2ef9d
 /* 
e2ef9d
-- 
e2ef9d
2.34.1
e2ef9d