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