[PATCH 5/5] Add lzma support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Alexey Gladkov <gladkov.alexey@xxxxxxxxx>
---
 Makefile.am     |    4 +++
 configure.ac    |   22 +++++++++++++++-
 depmod.c        |    2 +-
 grabfile.c      |   16 +++++++++++
 grabfile.h      |    3 +-
 grabfile_lzma.c |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 grabfile_lzma.h |    9 ++++++
 7 files changed, 129 insertions(+), 3 deletions(-)
 create mode 100644 grabfile_lzma.c
 create mode 100644 grabfile_lzma.h

diff --git a/Makefile.am b/Makefile.am
index 114d670..1f6bcee 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,6 +6,10 @@ if WITH_ZLIB
 grabfile_SOURCES += grabfile_zlib.c grabfile_zlib.h
 endif
 
+if WITH_LZMA
+grabfile_SOURCES += grabfile_lzma.c grabfile_lzma.h
+endif
+
 insmod_SOURCES = insmod.c testing.h
 lsmod_SOURCES = lsmod.c testing.h
 modprobe_SOURCES = modprobe.c testing.h $(grabfile_SOURCES)
diff --git a/configure.ac b/configure.ac
index 42629fa..4921d84 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,6 +31,26 @@ AC_ARG_ENABLE(zlib-dynamic,
 fi])
 AM_CONDITIONAL(WITH_ZLIB, test "$WITH_ZLIB" = "yes")
 
+WITH_LZMA=no
+
+AC_ARG_ENABLE(lzma,
+[  --enable-lzma               Handle lzma compressed modules],
+[if test "$enableval" = "yes"; then
+  WITH_LZMA=yes
+  AC_DEFINE(CONFIG_USE_LZMA)
+  lzma_flags="-Wl,-Bstatic -llzma -Wl,-Bdynamic"
+fi])
+
+AC_ARG_ENABLE(lzma,
+[  --enable-lzma-dynamic       Handle xz compressed modules, lzma will be linked
+                               dynamically.],
+[if test "$enableval" = "yes"; then
+  WITH_LZMA=yes
+  AC_DEFINE(CONFIG_USE_LZMA)
+  lzma_flags="-llzma"
+fi])
+AM_CONDITIONAL(WITH_LZMA, test "$WITH_LZMA" = "yes")
+
 AC_PROG_CC
 AC_PROG_RANLIB
 
@@ -44,7 +64,7 @@ fi
  
 # Delay adding the zlib_flags until after AC_PROG_CC, so we can distinguish
 # between a broken cc and a working cc but missing libz.a.
-LDADD="$LDADD $zlib_flags"
+LDADD="$LDADD $zlib_flags $lzma_flags"
 AC_SUBST(LDADD)
 
 case $target in
diff --git a/depmod.c b/depmod.c
index 3b5592e..3899513 100644
--- a/depmod.c
+++ b/depmod.c
@@ -698,7 +698,7 @@ static int output_deps_bin(struct module *modules,
  */
 static int smells_like_module(const char *name)
 {
-	return ends_in(name,".ko") || ends_in(name, ".ko.gz");
+	return ends_in(name,".ko") || ends_in(name, ".ko.gz") || ends_in(name, ".ko.xz");
 }
 
 typedef struct module *(*do_module_t)(const char *dirname,
diff --git a/grabfile.c b/grabfile.c
index d5a09ad..f402275 100644
--- a/grabfile.c
+++ b/grabfile.c
@@ -12,6 +12,10 @@
 #include "grabfile_zlib.h"
 #endif
 
+#ifdef CONFIG_USE_LZMA
+#include "grabfile_lzma.h"
+#endif
+
 static int compress_type(const char *filename)
 {
 	int fd;
@@ -27,6 +31,9 @@ static int compress_type(const char *filename)
 
 	close(fd);
 
+	if (buf[0] == 0xFD && buf[1] == '7' && buf[2] == 'z' && buf[3] == 'X' && buf[4] == 'Z' && buf[5] == 0x00)
+		return LZMA_FILE;
+
 	if (buf[0] == 0x1F && buf[1] == 0x8B)
 		return GZIP_FILE;
 
@@ -40,6 +47,10 @@ int grab_file(const char *filename, struct grab_data *fdata)
 		case GZIP_FILE:
 			return gzip_grab_file(filename, fdata);
 #endif
+#ifdef CONFIG_USE_LZMA
+		case LZMA_FILE:
+			return lzma_grab_file(filename, fdata);
+#endif
 		case PLAIN_FILE:
 			return plain_grab_file(filename, fdata);
 	}
@@ -55,6 +66,11 @@ void release_file(struct grab_data *fdata)
 			gzip_release_file(fdata);
 			return;
 #endif
+#ifdef CONFIG_USE_LZMA
+		case LZMA_FILE:
+			lzma_release_file(fdata);
+			return;
+#endif
 		case PLAIN_FILE:
 			plain_release_file(fdata);
 			return;
diff --git a/grabfile.h b/grabfile.h
index 99565db..c9b9545 100644
--- a/grabfile.h
+++ b/grabfile.h
@@ -4,7 +4,8 @@
 enum file_type
 {
 	PLAIN_FILE,
-	GZIP_FILE
+	GZIP_FILE,
+	LZMA_FILE
 };
 
 struct grab_data
diff --git a/grabfile_lzma.c b/grabfile_lzma.c
new file mode 100644
index 0000000..9418ac1
--- /dev/null
+++ b/grabfile_lzma.c
@@ -0,0 +1,76 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "grabfile_lzma.h"
+#include "logging.h"
+#include "testing.h"
+
+#include <lzma.h>
+
+#define IN_BUF_MAX 1024
+#define OUT_BUF_MAX 4096
+
+int lzma_grab_file(const char *filename, struct grab_data *fdata)
+{
+	int fd;
+	unsigned char *buffer = NULL;
+	unsigned char buf[IN_BUF_MAX];
+	size_t len;
+	lzma_ret ret;
+	lzma_stream strm = LZMA_STREAM_INIT;
+
+	fdata->data = NULL;
+	fdata->size = 0;
+
+	if ((fd = open(filename, O_RDONLY)) == -1) {
+		error("open: %s\n", strerror(errno));
+		return -1;
+	}
+
+	if ((ret = lzma_auto_decoder(&strm, UINT64_MAX, 0)) != LZMA_OK)
+		fatal("lzma_auto_decoder: return code = %d\n", (int) ret);
+
+	do {
+		if ((len = read(fd, &buf, IN_BUF_MAX)) == -1) {
+			if (errno == EINTR)
+				continue;
+			fatal("read: %s\n", strerror(errno));
+		}
+
+		strm.next_in  = buf;
+		strm.avail_in = len;
+
+		do {
+			buffer = NOFAIL(realloc(buffer, strm.total_out + OUT_BUF_MAX));
+			
+			strm.next_out  = buffer + strm.total_out;
+			strm.avail_out = OUT_BUF_MAX;
+
+			ret = lzma_code(&strm, (len == 0 ? LZMA_FINISH : LZMA_RUN));
+
+			if (ret != LZMA_OK && ret != LZMA_STREAM_END)
+				fatal("lzma_code: return code = %d\n", (int) ret);
+
+		} while (ret == LZMA_OK && strm.avail_in > 0);
+
+	} while (len > 0);
+
+	lzma_end(&strm);
+
+	fdata->type = LZMA_FILE;
+	fdata->data = buffer;
+	fdata->size = strm.total_out;
+
+	close(fd);
+	return 0;
+}
+
+void lzma_release_file(struct grab_data *fdata)
+{
+	free(fdata->data);
+}
diff --git a/grabfile_lzma.h b/grabfile_lzma.h
new file mode 100644
index 0000000..a6234cb
--- /dev/null
+++ b/grabfile_lzma.h
@@ -0,0 +1,9 @@
+#ifndef _GRABFILE_LZMA_H
+#define _GRABFILE_LZMA_H
+
+#include "grabfile.h"
+
+extern int lzma_grab_file(const char *filename, struct grab_data *fdata);
+extern void lzma_release_file(struct grab_data *fdata);
+
+#endif /* _GRABFILE_LZMA_H */
-- 
1.7.3.5

--
To unsubscribe from this list: send the line "unsubscribe linux-modules" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux