summaryrefslogtreecommitdiffstats
path: root/kexec/zlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'kexec/zlib.c')
-rw-r--r--kexec/zlib.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/kexec/zlib.c b/kexec/zlib.c
new file mode 100644
index 0000000..3ed6bd6
--- /dev/null
+++ b/kexec/zlib.c
@@ -0,0 +1,129 @@
+#include "kexec-zlib.h"
+#include "kexec.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>
+
+static void _gzerror(gzFile fp, int *errnum, const char **errmsg)
+{
+ *errmsg = gzerror(fp, errnum);
+ if (*errnum == Z_ERRNO) {
+ *errmsg = strerror(*errnum);
+ }
+}
+
+int is_zlib_file(const char *filename, off_t *r_size)
+{
+ gzFile fp;
+ int errnum;
+ int is_zlib_file = 0; /* default: It's not in gzip format */
+ const char *msg;
+ ssize_t result;
+
+ if (!filename)
+ goto out;
+
+ fp = gzopen(filename, "rb");
+ if (fp == 0) {
+ _gzerror(fp, &errnum, &msg);
+ dbgprintf("Cannot open `%s': %s\n", filename, msg);
+ goto out;
+ }
+
+ if (!gzdirect(fp))
+ /* It's in gzip format */
+ is_zlib_file = 1;
+
+ result = gzclose(fp);
+ if (result != Z_OK) {
+ _gzerror(fp, &errnum, &msg);
+ dbgprintf(" Close of %s failed: %s\n", filename, msg);
+ }
+
+out:
+ return is_zlib_file;
+}
+
+char *zlib_decompress_file(const char *filename, off_t *r_size)
+{
+ gzFile fp;
+ int errnum;
+ const char *msg;
+ char *buf = NULL;
+ off_t size = 0, allocated;
+ ssize_t result;
+
+ dbgprintf("Try gzip decompression.\n");
+
+ *r_size = 0;
+ if (!filename) {
+ return NULL;
+ }
+ fp = gzopen(filename, "rb");
+ if (fp == 0) {
+ _gzerror(fp, &errnum, &msg);
+ dbgprintf("Cannot open `%s': %s\n", filename, msg);
+ return NULL;
+ }
+ if (gzdirect(fp)) {
+ /* It's not in gzip format */
+ goto fail;
+ }
+ 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;
+ _gzerror(fp, &errnum, &msg);
+ dbgprintf("Read on %s of %d bytes failed: %s\n",
+ filename, (int)(allocated - size), msg);
+ size = 0;
+ goto fail;
+ }
+ size += result;
+ } while(result > 0);
+
+fail:
+ result = gzclose(fp);
+ if (result != Z_OK) {
+ _gzerror(fp, &errnum, &msg);
+ dbgprintf(" Close of %s failed: %s\n", filename, msg);
+ }
+
+ if (size > 0) {
+ *r_size = size;
+ } else {
+ free(buf);
+ buf = NULL;
+ }
+ return buf;
+}
+#else
+
+int is_zlib_file(const char *filename, off_t *r_size)
+{
+ return 0;
+}
+
+char *zlib_decompress_file(const char *UNUSED(filename), off_t *UNUSED(r_size))
+{
+ return NULL;
+}
+#endif /* HAVE_ZLIB */