1*2d543d20SAndroid Build Coastguard Worker /* Author: Jason Tang <[email protected]>
2*2d543d20SAndroid Build Coastguard Worker * Christopher Ashworth <[email protected]>
3*2d543d20SAndroid Build Coastguard Worker * Ondrej Mosnacek <[email protected]>
4*2d543d20SAndroid Build Coastguard Worker *
5*2d543d20SAndroid Build Coastguard Worker * Copyright (C) 2004-2006 Tresys Technology, LLC
6*2d543d20SAndroid Build Coastguard Worker * Copyright (C) 2005-2021 Red Hat, Inc.
7*2d543d20SAndroid Build Coastguard Worker *
8*2d543d20SAndroid Build Coastguard Worker * This library is free software; you can redistribute it and/or
9*2d543d20SAndroid Build Coastguard Worker * modify it under the terms of the GNU Lesser General Public
10*2d543d20SAndroid Build Coastguard Worker * License as published by the Free Software Foundation; either
11*2d543d20SAndroid Build Coastguard Worker * version 2.1 of the License, or (at your option) any later version.
12*2d543d20SAndroid Build Coastguard Worker *
13*2d543d20SAndroid Build Coastguard Worker * This library is distributed in the hope that it will be useful,
14*2d543d20SAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
15*2d543d20SAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16*2d543d20SAndroid Build Coastguard Worker * Lesser General Public License for more details.
17*2d543d20SAndroid Build Coastguard Worker *
18*2d543d20SAndroid Build Coastguard Worker * You should have received a copy of the GNU Lesser General Public
19*2d543d20SAndroid Build Coastguard Worker * License along with this library; if not, write to the Free Software
20*2d543d20SAndroid Build Coastguard Worker * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21*2d543d20SAndroid Build Coastguard Worker */
22*2d543d20SAndroid Build Coastguard Worker
23*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
24*2d543d20SAndroid Build Coastguard Worker #include <string.h>
25*2d543d20SAndroid Build Coastguard Worker #include <stdint.h>
26*2d543d20SAndroid Build Coastguard Worker
27*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
28*2d543d20SAndroid Build Coastguard Worker #include <fcntl.h>
29*2d543d20SAndroid Build Coastguard Worker
30*2d543d20SAndroid Build Coastguard Worker #include <bzlib.h>
31*2d543d20SAndroid Build Coastguard Worker
32*2d543d20SAndroid Build Coastguard Worker #include "compressed_file.h"
33*2d543d20SAndroid Build Coastguard Worker
34*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
35*2d543d20SAndroid Build Coastguard Worker
36*2d543d20SAndroid Build Coastguard Worker #define BZ2_MAGICSTR "BZh"
37*2d543d20SAndroid Build Coastguard Worker #define BZ2_MAGICLEN (sizeof(BZ2_MAGICSTR)-1)
38*2d543d20SAndroid Build Coastguard Worker
39*2d543d20SAndroid Build Coastguard Worker /* bzip() a data to a file, returning the total number of compressed bytes
40*2d543d20SAndroid Build Coastguard Worker * in the file. Returns -1 if file could not be compressed. */
bzip(semanage_handle_t * sh,const char * filename,void * data,size_t num_bytes)41*2d543d20SAndroid Build Coastguard Worker static int bzip(semanage_handle_t *sh, const char *filename, void *data,
42*2d543d20SAndroid Build Coastguard Worker size_t num_bytes)
43*2d543d20SAndroid Build Coastguard Worker {
44*2d543d20SAndroid Build Coastguard Worker BZFILE* b;
45*2d543d20SAndroid Build Coastguard Worker size_t size = 1<<16;
46*2d543d20SAndroid Build Coastguard Worker int bzerror;
47*2d543d20SAndroid Build Coastguard Worker size_t total = 0;
48*2d543d20SAndroid Build Coastguard Worker size_t len = 0;
49*2d543d20SAndroid Build Coastguard Worker FILE *f;
50*2d543d20SAndroid Build Coastguard Worker
51*2d543d20SAndroid Build Coastguard Worker if ((f = fopen(filename, "wb")) == NULL) {
52*2d543d20SAndroid Build Coastguard Worker return -1;
53*2d543d20SAndroid Build Coastguard Worker }
54*2d543d20SAndroid Build Coastguard Worker
55*2d543d20SAndroid Build Coastguard Worker if (!sh->conf->bzip_blocksize) {
56*2d543d20SAndroid Build Coastguard Worker if (fwrite(data, 1, num_bytes, f) < num_bytes) {
57*2d543d20SAndroid Build Coastguard Worker fclose(f);
58*2d543d20SAndroid Build Coastguard Worker return -1;
59*2d543d20SAndroid Build Coastguard Worker }
60*2d543d20SAndroid Build Coastguard Worker fclose(f);
61*2d543d20SAndroid Build Coastguard Worker return 0;
62*2d543d20SAndroid Build Coastguard Worker }
63*2d543d20SAndroid Build Coastguard Worker
64*2d543d20SAndroid Build Coastguard Worker b = BZ2_bzWriteOpen( &bzerror, f, sh->conf->bzip_blocksize, 0, 0);
65*2d543d20SAndroid Build Coastguard Worker if (bzerror != BZ_OK) {
66*2d543d20SAndroid Build Coastguard Worker BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
67*2d543d20SAndroid Build Coastguard Worker fclose(f);
68*2d543d20SAndroid Build Coastguard Worker return -1;
69*2d543d20SAndroid Build Coastguard Worker }
70*2d543d20SAndroid Build Coastguard Worker
71*2d543d20SAndroid Build Coastguard Worker while ( num_bytes > total ) {
72*2d543d20SAndroid Build Coastguard Worker if (num_bytes - total > size) {
73*2d543d20SAndroid Build Coastguard Worker len = size;
74*2d543d20SAndroid Build Coastguard Worker } else {
75*2d543d20SAndroid Build Coastguard Worker len = num_bytes - total;
76*2d543d20SAndroid Build Coastguard Worker }
77*2d543d20SAndroid Build Coastguard Worker BZ2_bzWrite ( &bzerror, b, (uint8_t *)data + total, len );
78*2d543d20SAndroid Build Coastguard Worker if (bzerror == BZ_IO_ERROR) {
79*2d543d20SAndroid Build Coastguard Worker BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
80*2d543d20SAndroid Build Coastguard Worker fclose(f);
81*2d543d20SAndroid Build Coastguard Worker return -1;
82*2d543d20SAndroid Build Coastguard Worker }
83*2d543d20SAndroid Build Coastguard Worker total += len;
84*2d543d20SAndroid Build Coastguard Worker }
85*2d543d20SAndroid Build Coastguard Worker
86*2d543d20SAndroid Build Coastguard Worker BZ2_bzWriteClose ( &bzerror, b, 0, 0, 0 );
87*2d543d20SAndroid Build Coastguard Worker fclose(f);
88*2d543d20SAndroid Build Coastguard Worker if (bzerror == BZ_IO_ERROR) {
89*2d543d20SAndroid Build Coastguard Worker return -1;
90*2d543d20SAndroid Build Coastguard Worker }
91*2d543d20SAndroid Build Coastguard Worker return 0;
92*2d543d20SAndroid Build Coastguard Worker }
93*2d543d20SAndroid Build Coastguard Worker
94*2d543d20SAndroid Build Coastguard Worker /* bunzip() a file to '*data', returning the total number of uncompressed bytes
95*2d543d20SAndroid Build Coastguard Worker * in the file. Returns -1 if file could not be decompressed. */
bunzip(semanage_handle_t * sh,FILE * f,void ** data)96*2d543d20SAndroid Build Coastguard Worker static ssize_t bunzip(semanage_handle_t *sh, FILE *f, void **data)
97*2d543d20SAndroid Build Coastguard Worker {
98*2d543d20SAndroid Build Coastguard Worker BZFILE* b = NULL;
99*2d543d20SAndroid Build Coastguard Worker size_t nBuf;
100*2d543d20SAndroid Build Coastguard Worker uint8_t* buf = NULL;
101*2d543d20SAndroid Build Coastguard Worker size_t size = 1<<18;
102*2d543d20SAndroid Build Coastguard Worker size_t bufsize = size;
103*2d543d20SAndroid Build Coastguard Worker int bzerror;
104*2d543d20SAndroid Build Coastguard Worker size_t total = 0;
105*2d543d20SAndroid Build Coastguard Worker uint8_t* uncompress = NULL;
106*2d543d20SAndroid Build Coastguard Worker uint8_t* tmpalloc = NULL;
107*2d543d20SAndroid Build Coastguard Worker int ret = -1;
108*2d543d20SAndroid Build Coastguard Worker
109*2d543d20SAndroid Build Coastguard Worker buf = malloc(bufsize);
110*2d543d20SAndroid Build Coastguard Worker if (buf == NULL) {
111*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
112*2d543d20SAndroid Build Coastguard Worker goto exit;
113*2d543d20SAndroid Build Coastguard Worker }
114*2d543d20SAndroid Build Coastguard Worker
115*2d543d20SAndroid Build Coastguard Worker /* Check if the file is bzipped */
116*2d543d20SAndroid Build Coastguard Worker bzerror = fread(buf, 1, BZ2_MAGICLEN, f);
117*2d543d20SAndroid Build Coastguard Worker
118*2d543d20SAndroid Build Coastguard Worker if (fseek(f, 0L, SEEK_SET) == -1) {
119*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure rewinding file.");
120*2d543d20SAndroid Build Coastguard Worker goto exit;
121*2d543d20SAndroid Build Coastguard Worker }
122*2d543d20SAndroid Build Coastguard Worker
123*2d543d20SAndroid Build Coastguard Worker if ((bzerror != BZ2_MAGICLEN) || memcmp(buf, BZ2_MAGICSTR, BZ2_MAGICLEN)) {
124*2d543d20SAndroid Build Coastguard Worker goto exit;
125*2d543d20SAndroid Build Coastguard Worker }
126*2d543d20SAndroid Build Coastguard Worker
127*2d543d20SAndroid Build Coastguard Worker b = BZ2_bzReadOpen ( &bzerror, f, 0, sh->conf->bzip_small, NULL, 0 );
128*2d543d20SAndroid Build Coastguard Worker if ( bzerror != BZ_OK ) {
129*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure opening bz2 archive.");
130*2d543d20SAndroid Build Coastguard Worker goto exit;
131*2d543d20SAndroid Build Coastguard Worker }
132*2d543d20SAndroid Build Coastguard Worker
133*2d543d20SAndroid Build Coastguard Worker uncompress = malloc(size);
134*2d543d20SAndroid Build Coastguard Worker if (uncompress == NULL) {
135*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
136*2d543d20SAndroid Build Coastguard Worker goto exit;
137*2d543d20SAndroid Build Coastguard Worker }
138*2d543d20SAndroid Build Coastguard Worker
139*2d543d20SAndroid Build Coastguard Worker while ( bzerror == BZ_OK) {
140*2d543d20SAndroid Build Coastguard Worker nBuf = BZ2_bzRead ( &bzerror, b, buf, bufsize);
141*2d543d20SAndroid Build Coastguard Worker if (( bzerror == BZ_OK ) || ( bzerror == BZ_STREAM_END )) {
142*2d543d20SAndroid Build Coastguard Worker if (total + nBuf > size) {
143*2d543d20SAndroid Build Coastguard Worker size *= 2;
144*2d543d20SAndroid Build Coastguard Worker tmpalloc = realloc(uncompress, size);
145*2d543d20SAndroid Build Coastguard Worker if (tmpalloc == NULL) {
146*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
147*2d543d20SAndroid Build Coastguard Worker goto exit;
148*2d543d20SAndroid Build Coastguard Worker }
149*2d543d20SAndroid Build Coastguard Worker uncompress = tmpalloc;
150*2d543d20SAndroid Build Coastguard Worker }
151*2d543d20SAndroid Build Coastguard Worker memcpy(&uncompress[total], buf, nBuf);
152*2d543d20SAndroid Build Coastguard Worker total += nBuf;
153*2d543d20SAndroid Build Coastguard Worker }
154*2d543d20SAndroid Build Coastguard Worker }
155*2d543d20SAndroid Build Coastguard Worker if ( bzerror != BZ_STREAM_END ) {
156*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure reading bz2 archive.");
157*2d543d20SAndroid Build Coastguard Worker goto exit;
158*2d543d20SAndroid Build Coastguard Worker }
159*2d543d20SAndroid Build Coastguard Worker
160*2d543d20SAndroid Build Coastguard Worker ret = total;
161*2d543d20SAndroid Build Coastguard Worker *data = uncompress;
162*2d543d20SAndroid Build Coastguard Worker
163*2d543d20SAndroid Build Coastguard Worker exit:
164*2d543d20SAndroid Build Coastguard Worker BZ2_bzReadClose ( &bzerror, b );
165*2d543d20SAndroid Build Coastguard Worker free(buf);
166*2d543d20SAndroid Build Coastguard Worker if ( ret < 0 ) {
167*2d543d20SAndroid Build Coastguard Worker free(uncompress);
168*2d543d20SAndroid Build Coastguard Worker }
169*2d543d20SAndroid Build Coastguard Worker return ret;
170*2d543d20SAndroid Build Coastguard Worker }
171*2d543d20SAndroid Build Coastguard Worker
map_compressed_file(semanage_handle_t * sh,const char * path,struct file_contents * contents)172*2d543d20SAndroid Build Coastguard Worker int map_compressed_file(semanage_handle_t *sh, const char *path,
173*2d543d20SAndroid Build Coastguard Worker struct file_contents *contents)
174*2d543d20SAndroid Build Coastguard Worker {
175*2d543d20SAndroid Build Coastguard Worker ssize_t size = -1;
176*2d543d20SAndroid Build Coastguard Worker void *uncompress;
177*2d543d20SAndroid Build Coastguard Worker int ret = 0, fd = -1;
178*2d543d20SAndroid Build Coastguard Worker FILE *file = NULL;
179*2d543d20SAndroid Build Coastguard Worker
180*2d543d20SAndroid Build Coastguard Worker fd = open(path, O_RDONLY);
181*2d543d20SAndroid Build Coastguard Worker if (fd == -1) {
182*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to open %s\n", path);
183*2d543d20SAndroid Build Coastguard Worker return -1;
184*2d543d20SAndroid Build Coastguard Worker }
185*2d543d20SAndroid Build Coastguard Worker
186*2d543d20SAndroid Build Coastguard Worker file = fdopen(fd, "r");
187*2d543d20SAndroid Build Coastguard Worker if (file == NULL) {
188*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to open %s\n", path);
189*2d543d20SAndroid Build Coastguard Worker close(fd);
190*2d543d20SAndroid Build Coastguard Worker return -1;
191*2d543d20SAndroid Build Coastguard Worker }
192*2d543d20SAndroid Build Coastguard Worker
193*2d543d20SAndroid Build Coastguard Worker if ((size = bunzip(sh, file, &uncompress)) >= 0) {
194*2d543d20SAndroid Build Coastguard Worker contents->data = uncompress;
195*2d543d20SAndroid Build Coastguard Worker contents->len = size;
196*2d543d20SAndroid Build Coastguard Worker contents->compressed = 1;
197*2d543d20SAndroid Build Coastguard Worker } else {
198*2d543d20SAndroid Build Coastguard Worker struct stat sb;
199*2d543d20SAndroid Build Coastguard Worker if (fstat(fd, &sb) == -1 ||
200*2d543d20SAndroid Build Coastguard Worker (uncompress = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) ==
201*2d543d20SAndroid Build Coastguard Worker MAP_FAILED) {
202*2d543d20SAndroid Build Coastguard Worker ret = -1;
203*2d543d20SAndroid Build Coastguard Worker } else {
204*2d543d20SAndroid Build Coastguard Worker contents->data = uncompress;
205*2d543d20SAndroid Build Coastguard Worker contents->len = sb.st_size;
206*2d543d20SAndroid Build Coastguard Worker contents->compressed = 0;
207*2d543d20SAndroid Build Coastguard Worker }
208*2d543d20SAndroid Build Coastguard Worker }
209*2d543d20SAndroid Build Coastguard Worker fclose(file);
210*2d543d20SAndroid Build Coastguard Worker return ret;
211*2d543d20SAndroid Build Coastguard Worker }
212*2d543d20SAndroid Build Coastguard Worker
unmap_compressed_file(struct file_contents * contents)213*2d543d20SAndroid Build Coastguard Worker void unmap_compressed_file(struct file_contents *contents)
214*2d543d20SAndroid Build Coastguard Worker {
215*2d543d20SAndroid Build Coastguard Worker if (!contents->data)
216*2d543d20SAndroid Build Coastguard Worker return;
217*2d543d20SAndroid Build Coastguard Worker
218*2d543d20SAndroid Build Coastguard Worker if (contents->compressed) {
219*2d543d20SAndroid Build Coastguard Worker free(contents->data);
220*2d543d20SAndroid Build Coastguard Worker } else {
221*2d543d20SAndroid Build Coastguard Worker munmap(contents->data, contents->len);
222*2d543d20SAndroid Build Coastguard Worker }
223*2d543d20SAndroid Build Coastguard Worker }
224*2d543d20SAndroid Build Coastguard Worker
write_compressed_file(semanage_handle_t * sh,const char * path,void * data,size_t len)225*2d543d20SAndroid Build Coastguard Worker int write_compressed_file(semanage_handle_t *sh, const char *path,
226*2d543d20SAndroid Build Coastguard Worker void *data, size_t len)
227*2d543d20SAndroid Build Coastguard Worker {
228*2d543d20SAndroid Build Coastguard Worker return bzip(sh, path, data, len);
229*2d543d20SAndroid Build Coastguard Worker }
230