summaryrefslogtreecommitdiff
path: root/kexec/zlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'kexec/zlib.c')
-rw-r--r--kexec/zlib.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/kexec/zlib.c b/kexec/zlib.c
new file mode 100644
index 0000000..3968494
--- /dev/null
+++ b/kexec/zlib.c
@@ -0,0 +1,78 @@
+#include "kexec-zlib.h"
+#ifdef HAVE_LIBZ
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <zlib.h>
+
+#include "kexec.h"
+
+char *zlib_decompress_file(const char *filename, off_t *r_size)
+{
+ gzFile fp;
+ int errnum;
+ const char *msg;
+ char *buf;
+ off_t size, allocated;
+ ssize_t result;
+
+ if (!filename) {
+ *r_size = 0;
+ return 0;
+ }
+ fp = gzopen(filename, "rb");
+ if (fp == 0) {
+ msg = gzerror(fp, &errnum);
+ if (errnum == Z_ERRNO) {
+ msg = strerror(errno);
+ }
+ fprintf(stderr, "Cannot open `%s': %s\n", filename, msg);
+ return NULL;
+ }
+ size = 0;
+ allocated = 65536;
+ buf = xmalloc(allocated);
+ do {
+ if (size == allocated) {
+ allocated <<= 1;
+ buf = xrealloc(buf, allocated);
+ }
+ result = gzread(fp, buf + size, allocated - size);
+ if (result < 0) {
+ if ((errno == EINTR) || (errno == EAGAIN))
+ continue;
+
+ msg = gzerror(fp, &errnum);
+ if (errnum == Z_ERRNO) {
+ msg = strerror(errno);
+ }
+ die ("read on %s of %ld bytes failed: %s\n",
+ filename, (allocated - size) + 0UL, msg);
+ }
+ size += result;
+ } while(result > 0);
+ result = gzclose(fp);
+ if (result != Z_OK) {
+ msg = gzerror(fp, &errnum);
+ if (errnum == Z_ERRNO) {
+ msg = strerror(errno);
+ }
+ die ("Close of %s failed: %s\n", filename, msg);
+ }
+ *r_size = size;
+ return buf;
+}
+#else
+char *zlib_decompress_file(const char *filename, off_t *r_size)
+{
+ return NULL;
+}
+#endif /* HAVE_ZLIB */