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