import-compress.c revision 8b43440b7ef4b81c69c31de7ff820dc07a780254
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2015 Lennart Poettering
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.
systemd 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 systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "import-compress.h"
#include "string-table.h"
#include "util.h"
void import_compress_free(ImportCompress *c) {
assert(c);
if (c->type == IMPORT_COMPRESS_XZ)
else if (c->type == IMPORT_COMPRESS_GZIP) {
if (c->encoding)
deflateEnd(&c->gzip);
else
inflateEnd(&c->gzip);
} else if (c->type == IMPORT_COMPRESS_BZIP2) {
if (c->encoding)
BZ2_bzCompressEnd(&c->bzip2);
else
BZ2_bzDecompressEnd(&c->bzip2);
}
c->type = IMPORT_COMPRESS_UNKNOWN;
}
static const uint8_t xz_signature[] = {
0xfd, '7', 'z', 'X', 'Z', 0x00
};
static const uint8_t gzip_signature[] = {
0x1f, 0x8b
};
static const uint8_t bzip2_signature[] = {
'B', 'Z', 'h'
};
int r;
assert(c);
if (c->type != IMPORT_COMPRESS_UNKNOWN)
return 1;
sizeof(gzip_signature),
sizeof(bzip2_signature)))
return 0;
return -EIO;
c->type = IMPORT_COMPRESS_XZ;
if (r != Z_OK)
return -EIO;
c->type = IMPORT_COMPRESS_GZIP;
r = BZ2_bzDecompressInit(&c->bzip2, 0, 0);
if (r != BZ_OK)
return -EIO;
c->type = IMPORT_COMPRESS_BZIP2;
} else
c->encoding = false;
return 1;
}
int import_uncompress(ImportCompress *c, const void *data, size_t size, ImportCompressCallback callback, void *userdata) {
int r;
assert(c);
if (r <= 0)
return r;
if (c->encoding)
return -EINVAL;
if (size <= 0)
return 1;
switch (c->type) {
if (r < 0)
return r;
break;
case IMPORT_COMPRESS_XZ:
return -EIO;
if (r < 0)
return r;
}
break;
case IMPORT_COMPRESS_GZIP:
if (r != Z_OK && r != Z_STREAM_END)
return -EIO;
if (r < 0)
return r;
}
break;
case IMPORT_COMPRESS_BZIP2:
r = BZ2_bzDecompress(&c->bzip2);
if (r != BZ_OK && r != BZ_STREAM_END)
return -EIO;
if (r < 0)
return r;
}
break;
default:
assert_not_reached("Unknown compression");
}
return 1;
}
int r;
assert(c);
switch (t) {
case IMPORT_COMPRESS_XZ: {
return -EIO;
c->type = IMPORT_COMPRESS_XZ;
break;
}
case IMPORT_COMPRESS_GZIP:
if (r != Z_OK)
return -EIO;
c->type = IMPORT_COMPRESS_GZIP;
break;
case IMPORT_COMPRESS_BZIP2:
if (r != BZ_OK)
return -EIO;
c->type = IMPORT_COMPRESS_BZIP2;
break;
break;
default:
return -EOPNOTSUPP;
}
c->encoding = true;
return 0;
}
size_t l;
void *p;
if (*buffer_allocated > *buffer_size)
return 0;
if (!p)
return -ENOMEM;
*buffer = p;
*buffer_allocated = l;
return 1;
}
int import_compress(ImportCompress *c, const void *data, size_t size, void **buffer, size_t *buffer_size, size_t *buffer_allocated) {
int r;
assert(c);
if (!c->encoding)
return -EINVAL;
if (size <= 0)
return 0;
*buffer_size = 0;
switch (c->type) {
case IMPORT_COMPRESS_XZ:
if (r < 0)
return r;
return -EIO;
}
break;
case IMPORT_COMPRESS_GZIP:
if (r < 0)
return r;
if (r != Z_OK)
return -EIO;
}
break;
case IMPORT_COMPRESS_BZIP2:
if (r < 0)
return r;
if (r != BZ_RUN_OK)
return -EIO;
}
break;
if (*buffer_allocated < size) {
void *p;
if (!p)
return -ENOMEM;
*buffer = p;
*buffer_allocated = size;
}
*buffer_size = size;
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
int import_compress_finish(ImportCompress *c, void **buffer, size_t *buffer_size, size_t *buffer_allocated) {
int r;
assert(c);
if (!c->encoding)
return -EINVAL;
*buffer_size = 0;
switch (c->type) {
case IMPORT_COMPRESS_XZ: {
do {
if (r < 0)
return r;
return -EIO;
} while (lzr != LZMA_STREAM_END);
break;
}
case IMPORT_COMPRESS_GZIP:
do {
if (r < 0)
return r;
if (r != Z_OK && r != Z_STREAM_END)
return -EIO;
} while (r != Z_STREAM_END);
break;
case IMPORT_COMPRESS_BZIP2:
do {
if (r < 0)
return r;
if (r != BZ_FINISH_OK && r != BZ_STREAM_END)
return -EIO;
} while (r != BZ_STREAM_END);
break;
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
static const char* const import_compress_type_table[_IMPORT_COMPRESS_TYPE_MAX] = {
[IMPORT_COMPRESS_UNKNOWN] = "unknown",
[IMPORT_COMPRESS_UNCOMPRESSED] = "uncompressed",
[IMPORT_COMPRESS_XZ] = "xz",
[IMPORT_COMPRESS_GZIP] = "gzip",
[IMPORT_COMPRESS_BZIP2] = "bzip2",
};