aboutsummaryrefslogtreecommitdiffstats
path: root/tools/squashfs4
diff options
context:
space:
mode:
authorJames <>2015-11-04 11:49:21 +0000
committerJames <>2015-11-04 11:49:21 +0000
commit716ca530e1c4515d8683c9d5be3d56b301758b66 (patch)
tree700eb5bcc1a462a5f21dcec15ce7c97ecfefa772 /tools/squashfs4
downloadtrunk-47381-master.tar.gz
trunk-47381-master.tar.bz2
trunk-47381-master.zip
trunk-47381HEADmaster
Diffstat (limited to 'tools/squashfs4')
-rw-r--r--tools/squashfs4/Makefile42
-rw-r--r--tools/squashfs4/patches/100-portability.patch40
-rw-r--r--tools/squashfs4/patches/110-allow_static_liblzma.patch30
-rw-r--r--tools/squashfs4/patches/120-cygwin_fixes.patch153
-rw-r--r--tools/squashfs4/patches/150-freebsd_fixes.patch10
-rw-r--r--tools/squashfs4/patches/160-expose_lzma_xz_options.patch929
-rw-r--r--tools/squashfs4/patches/170-add_support_for_LZMA_MAGIC_to_unsqashfs.patch72
-rw-r--r--tools/squashfs4/patches/180-openbsd_compat.patch26
-rw-r--r--tools/squashfs4/patches/190-no_nonstatic_inline.patch36
9 files changed, 1338 insertions, 0 deletions
diff --git a/tools/squashfs4/Makefile b/tools/squashfs4/Makefile
new file mode 100644
index 0000000..50b70fb
--- /dev/null
+++ b/tools/squashfs4/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2009-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=squashfs4
+PKG_VERSION:=4.2
+
+PKG_SOURCE:=squashfs$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/squashfs
+PKG_MD5SUM:=1b7a781fb4cf8938842279bd3e8ee852
+PKG_CAT:=zcat
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/squashfs$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR)/squashfs-tools \
+ CC="$(HOSTCC)" \
+ XZ_SUPPORT=1 \
+ LZMA_XZ_SUPPORT=1 \
+ XATTR_SUPPORT= \
+ LZMA_LIB="$(STAGING_DIR_HOST)/lib/liblzma.a" \
+ EXTRA_CFLAGS="-I$(STAGING_DIR_HOST)/include" \
+ mksquashfs unsquashfs
+endef
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/squashfs-tools/mksquashfs $(STAGING_DIR_HOST)/bin/mksquashfs4
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/squashfs-tools/unsquashfs $(STAGING_DIR_HOST)/bin/unsquashfs4
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/mksquashfs4
+ rm -f $(STAGING_DIR_HOST)/bin/unsquashfs4
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/squashfs4/patches/100-portability.patch b/tools/squashfs4/patches/100-portability.patch
new file mode 100644
index 0000000..ac1349c
--- /dev/null
+++ b/tools/squashfs4/patches/100-portability.patch
@@ -0,0 +1,40 @@
+--- a/squashfs-tools/mksquashfs.c
++++ b/squashfs-tools/mksquashfs.c
+@@ -60,6 +60,10 @@
+ #include <sys/sysinfo.h>
+ #endif
+
++#ifndef FNM_EXTMATCH
++#define FNM_EXTMATCH 0
++#endif
++
+ #ifdef SQUASHFS_TRACE
+ #define TRACE(s, args...) \
+ do { \
+--- a/squashfs-tools/unsquashfs.h
++++ b/squashfs-tools/unsquashfs.h
+@@ -49,8 +49,14 @@
+ #define __BYTE_ORDER BYTE_ORDER
+ #define __BIG_ENDIAN BIG_ENDIAN
+ #define __LITTLE_ENDIAN LITTLE_ENDIAN
++#include <sys/sysctl.h>
+ #else
+ #include <endian.h>
++#include <sys/sysinfo.h>
++#endif
++
++#ifndef FNM_EXTMATCH
++#define FNM_EXTMATCH 0
+ #endif
+
+ #include "squashfs_fs.h"
+--- a/squashfs-tools/unsquashfs.c
++++ b/squashfs-tools/unsquashfs.c
+@@ -29,7 +29,6 @@
+ #include "compressor.h"
+ #include "xattr.h"
+
+-#include <sys/sysinfo.h>
+ #include <sys/types.h>
+
+ struct cache *fragment_cache, *data_cache;
diff --git a/tools/squashfs4/patches/110-allow_static_liblzma.patch b/tools/squashfs4/patches/110-allow_static_liblzma.patch
new file mode 100644
index 0000000..9a3a744
--- /dev/null
+++ b/tools/squashfs4/patches/110-allow_static_liblzma.patch
@@ -0,0 +1,30 @@
+--- a/squashfs-tools/Makefile
++++ b/squashfs-tools/Makefile
+@@ -129,7 +129,6 @@ ifeq ($(LZMA_XZ_SUPPORT),1)
+ CFLAGS += -DLZMA_SUPPORT
+ MKSQUASHFS_OBJS += lzma_xz_wrapper.o
+ UNSQUASHFS_OBJS += lzma_xz_wrapper.o
+-LIBS += -llzma
+ COMPRESSORS += lzma
+ endif
+
+@@ -137,10 +136,18 @@ ifeq ($(XZ_SUPPORT),1)
+ CFLAGS += -DXZ_SUPPORT
+ MKSQUASHFS_OBJS += xz_wrapper.o
+ UNSQUASHFS_OBJS += xz_wrapper.o
+-LIBS += -llzma
+ COMPRESSORS += xz
+ endif
+
++ifneq ($(LZMA_XZ_SUPPORT)$(XZ_SUPPORT),)
++ifneq ($(LZMA_LIB),)
++MKSQUASHFS_OBJS += $(LZMA_LIB)
++UNSQUASHFS_OBJS += $(LZMA_LIB)
++else
++LIBS += -llzma
++endif
++endif
++
+ ifeq ($(LZO_SUPPORT),1)
+ CFLAGS += -DLZO_SUPPORT
+ ifdef LZO_DIR
diff --git a/tools/squashfs4/patches/120-cygwin_fixes.patch b/tools/squashfs4/patches/120-cygwin_fixes.patch
new file mode 100644
index 0000000..fa1dfba
--- /dev/null
+++ b/tools/squashfs4/patches/120-cygwin_fixes.patch
@@ -0,0 +1,153 @@
+--- a/squashfs-tools/mksquashfs.c
++++ b/squashfs-tools/mksquashfs.c
+@@ -51,15 +51,22 @@
+ #include <sys/wait.h>
+
+ #ifndef linux
++#ifndef __CYGWIN__
+ #define __BYTE_ORDER BYTE_ORDER
+ #define __BIG_ENDIAN BIG_ENDIAN
+ #define __LITTLE_ENDIAN LITTLE_ENDIAN
+ #include <sys/sysctl.h>
++#endif /* __CYGWIN__ */
+ #else
+ #include <endian.h>
+ #include <sys/sysinfo.h>
+ #endif
+
++#ifdef __CYGWIN__
++#include <sys/termios.h>
++#define FNM_EXTMATCH (1 << 5)
++#endif
++
+ #ifndef FNM_EXTMATCH
+ #define FNM_EXTMATCH 0
+ #endif
+@@ -844,6 +851,7 @@ void sigusr1_handler()
+
+ void sigwinch_handler()
+ {
++#ifndef __CYGWIN__
+ struct winsize winsize;
+
+ if(ioctl(1, TIOCGWINSZ, &winsize) == -1) {
+@@ -853,6 +861,9 @@ void sigwinch_handler()
+ columns = 80;
+ } else
+ columns = winsize.ws_col;
++#else
++ columns = 80;
++#endif
+ }
+
+
+@@ -4066,6 +4077,9 @@ void initialise_threads(int readb_mbytes
+
+ signal(SIGUSR1, sigusr1_handler);
+
++#ifdef __CYGWIN__
++ processors = atoi(getenv("NUMBER_OF_PROCESSORS"));
++#else
+ if(processors == -1) {
+ #ifndef linux
+ int mib[2];
+@@ -4087,6 +4101,7 @@ void initialise_threads(int readb_mbytes
+ processors = sysconf(_SC_NPROCESSORS_ONLN);
+ #endif
+ }
++#endif /* __CYGWIN__ */
+
+ thread = malloc((2 + processors * 2) * sizeof(pthread_t));
+ if(thread == NULL)
+--- a/squashfs-tools/read_fs.c
++++ b/squashfs-tools/read_fs.c
+@@ -33,9 +33,11 @@
+ #include <sys/mman.h>
+
+ #ifndef linux
++#ifndef __CYGWIN__
+ #define __BYTE_ORDER BYTE_ORDER
+ #define __BIG_ENDIAN BIG_ENDIAN
+ #define __LITTLE_ENDIAN LITTLE_ENDIAN
++#endif
+ #else
+ #include <endian.h>
+ #endif
+--- a/squashfs-tools/swap.c
++++ b/squashfs-tools/swap.c
+@@ -20,9 +20,11 @@
+ */
+
+ #ifndef linux
++#ifndef __CYGWIN__
+ #define __BYTE_ORDER BYTE_ORDER
+ #define __BIG_ENDIAN BIG_ENDIAN
+ #define __LITTLE_ENDIAN LITTLE_ENDIAN
++#endif
+ #else
+ #include <endian.h>
+ #endif
+--- a/squashfs-tools/unsquashfs.c
++++ b/squashfs-tools/unsquashfs.c
+@@ -117,6 +117,7 @@ void update_progress_bar();
+
+ void sigwinch_handler()
+ {
++#ifndef __CYGWIN__
+ struct winsize winsize;
+
+ if(ioctl(1, TIOCGWINSZ, &winsize) == -1) {
+@@ -126,6 +127,9 @@ void sigwinch_handler()
+ columns = 80;
+ } else
+ columns = winsize.ws_col;
++#else
++ columns = 80;
++#endif
+ }
+
+
+@@ -1807,7 +1811,9 @@ void initialise_threads(int fragment_buf
+ if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1)
+ EXIT_UNSQUASH("Failed to set signal mask in intialise_threads"
+ "\n");
+-
++#ifdef __CYGWIN__
++ processors = atoi(getenv("NUMBER_OF_PROCESSORS"));
++#else
+ if(processors == -1) {
+ #ifndef linux
+ int mib[2];
+@@ -1829,6 +1835,7 @@ void initialise_threads(int fragment_buf
+ processors = sysconf(_SC_NPROCESSORS_ONLN);
+ #endif
+ }
++#endif /* __CYGWIN__ */
+
+ thread = malloc((3 + processors) * sizeof(pthread_t));
+ if(thread == NULL)
+--- a/squashfs-tools/unsquashfs.h
++++ b/squashfs-tools/unsquashfs.h
+@@ -46,15 +46,22 @@
+ #include <sys/time.h>
+
+ #ifndef linux
++#ifndef __CYGWIN__
+ #define __BYTE_ORDER BYTE_ORDER
+ #define __BIG_ENDIAN BIG_ENDIAN
+ #define __LITTLE_ENDIAN LITTLE_ENDIAN
+ #include <sys/sysctl.h>
++#endif
+ #else
+ #include <endian.h>
+ #include <sys/sysinfo.h>
+ #endif
+
++#ifdef __CYGWIN__
++#include <sys/termios.h>
++#define FNM_EXTMATCH (1 << 5)
++#endif
++
+ #ifndef FNM_EXTMATCH
+ #define FNM_EXTMATCH 0
+ #endif
diff --git a/tools/squashfs4/patches/150-freebsd_fixes.patch b/tools/squashfs4/patches/150-freebsd_fixes.patch
new file mode 100644
index 0000000..44d40a7
--- /dev/null
+++ b/tools/squashfs4/patches/150-freebsd_fixes.patch
@@ -0,0 +1,10 @@
+--- a/squashfs-tools/pseudo.c
++++ b/squashfs-tools/pseudo.c
+@@ -32,6 +32,7 @@
+ #include <stdlib.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
++#include <sys/stat.h>
+
+ #include "pseudo.h"
+
diff --git a/tools/squashfs4/patches/160-expose_lzma_xz_options.patch b/tools/squashfs4/patches/160-expose_lzma_xz_options.patch
new file mode 100644
index 0000000..d606396
--- /dev/null
+++ b/tools/squashfs4/patches/160-expose_lzma_xz_options.patch
@@ -0,0 +1,929 @@
+--- /dev/null
++++ b/squashfs-tools/lzma_xz_options.h
+@@ -0,0 +1,115 @@
++#ifndef LZMA_XZ_OPTIONS_H
++#define LZMA_XZ_OPTIONS_H
++/*
++ * Copyright (c) 2011
++ * Jonas Gorski <jonas.gorski@gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program 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 General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * lzma_options.h
++ */
++
++#include <stdint.h>
++
++#ifndef linux
++#ifdef __FreeBSD__
++#include <machine/endian.h>
++#endif
++#define __BYTE_ORDER BYTE_ORDER
++#define __BIG_ENDIAN BIG_ENDIAN
++#define __LITTLE_ENDIAN LITTLE_ENDIAN
++#else
++#include <endian.h>
++#endif
++
++
++
++struct lzma_opts {
++ uint32_t flags;
++#define LZMA_OPT_FLT_MASK 0xffff
++#define LZMA_OPT_PRE_OFF 16
++#define LZMA_OPT_PRE_MASK (0xf << LZMA_OPT_PRE_OFF)
++#define LZMA_OPT_EXTREME 20
++ uint16_t bit_opts;
++#define LZMA_OPT_LC_OFF 0
++#define LZMA_OPT_LC_MASK (0x7 << LZMA_OPT_LC_OFF)
++#define LZMA_OPT_LP_OFF 3
++#define LZMA_OPT_LP_MASK (0x7 << LZMA_OPT_LP_OFF)
++#define LZMA_OPT_PB_OFF 6
++#define LZMA_OPT_PB_MASK (0x7 << LZMA_OPT_PB_OFF)
++ uint16_t fb;
++ uint32_t dict_size;
++};
++
++#if __BYTE_ORDER == __BIG_ENDIAN
++extern unsigned int inswap_le32(unsigned int);
++
++#define SQUASHFS_INSWAP_LZMA_COMP_OPTS(s) { \
++ (s)->flags = inswap_le32((s)->flags); \
++ (s)->bit_opts = inswap_le16((s)->bit_opts); \
++ (s)->fb = inswap_le16((s)->fb); \
++ (s)->dict_size = inswap_le32((s)->dict_size); \
++}
++#else
++#define SQUASHFS_INSWAP_LZMA_COMP_OPTS(s)
++#endif
++
++#define MEMLIMIT (32 * 1024 * 1024)
++
++#define LZMA_OPT_LC_MIN 0
++#define LZMA_OPT_LC_MAX 4
++#define LZMA_OPT_LC_DEFAULT 3
++
++#define LZMA_OPT_LP_MIN 0
++#define LZMA_OPT_LP_MAX 4
++#define LZMA_OPT_LP_DEFAULT 0
++
++#define LZMA_OPT_PB_MIN 0
++#define LZMA_OPT_PB_MAX 4
++#define LZMA_OPT_PB_DEFAULT 2
++
++#define LZMA_OPT_FB_MIN 5
++#define LZMA_OPT_FB_MAX 273
++#define LZMA_OPT_FB_DEFAULT 64
++
++enum {
++ LZMA_OPT_LZMA = 1,
++ LZMA_OPT_XZ
++};
++
++struct lzma_xz_options {
++ int preset;
++ int extreme;
++ int lc;
++ int lp;
++ int pb;
++ int fb;
++ int dict_size;
++ int flags;
++};
++
++struct lzma_xz_options *lzma_xz_get_options(void);
++
++int lzma_xz_options(char *argv[], int argc, int lzmaver);
++
++int lzma_xz_options_post(int block_size, int lzmaver);
++
++void *lzma_xz_dump_options(int block_size, int *size, int flags);
++
++int lzma_xz_extract_options(int block_size, void *buffer, int size, int lzmaver);
++
++void lzma_xz_usage(int lzmaver);
++
++#endif
+--- /dev/null
++++ b/squashfs-tools/lzma_xz_options.c
+@@ -0,0 +1,365 @@
++/*
++ * Copyright (c) 2011
++ * Jonas Gorski <jonas.gorski@gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program 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 General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * lzma_options.c
++ *
++ * Common options for LZMA1 and 2 compressors. Based on xz_wrapper.c
++ */
++
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++
++#include <lzma.h>
++
++#include "lzma_xz_options.h"
++
++static const char const *lzmaver_str[] = { "", "lzma", "xz" };
++
++static struct lzma_xz_options options = {
++ .flags = 0,
++ .preset = 6,
++ .extreme = 0,
++ .lc = LZMA_OPT_LC_DEFAULT,
++ .lp = LZMA_OPT_LP_DEFAULT,
++ .pb = LZMA_OPT_PB_DEFAULT,
++ .fb = LZMA_OPT_FB_DEFAULT,
++ .dict_size = 0,
++};
++
++static float lzma_dict_percent = 0;
++
++struct lzma_xz_options *lzma_xz_get_options(void)
++{
++ return &options;
++}
++
++
++int lzma_xz_options(char *argv[], int argc, int lzmaver)
++{
++ const char *comp_name = lzmaver_str[lzmaver];
++
++ if(strcmp(argv[0], "-Xpreset") == 0) {
++ int preset;
++
++ if(argc < 2) {
++ fprintf(stderr, "%s: -Xpreset missing preset\n", comp_name);
++ goto failed;
++ }
++
++ preset = atoi(argv[1]);
++
++ if (preset < 0 || preset > 9) {
++ fprintf(stderr, "%s: -Xpreset invalid value\n", comp_name);
++ goto failed;
++ }
++ options.preset = preset;
++ return 1;
++ } else if(strcmp(argv[0], "-Xe") == 0) {
++ options.extreme = 1;
++ return 0;
++ } else if(strcmp(argv[0], "-Xlc") == 0) {
++ int lc;
++
++ if(argc < 2) {
++ fprintf(stderr, "%s: -Xlc missing lc\n", comp_name);
++ goto failed;
++ }
++
++ lc = atoi(argv[1]);
++
++ if (lc < LZMA_OPT_LC_MIN || lc > LZMA_OPT_LC_MAX) {
++ fprintf(stderr, "%s: -Xlc invalid value\n", comp_name);
++ goto failed;
++ }
++ options.lc = lc;
++ return 1;
++ } else if(strcmp(argv[0], "-Xlp") == 0) {
++ int lp;
++
++ if(argc < 2) {
++ fprintf(stderr, "%s: -Xlp missing lp\n", comp_name);
++ goto failed;
++ }
++
++ lp = atoi(argv[1]);
++
++ if (lp < LZMA_OPT_LP_MIN || lp > LZMA_OPT_LP_MAX) {
++ fprintf(stderr, "%s: -Xlp invalid value\n", comp_name);
++ goto failed;
++ }
++ options.lp = lp;
++ return 1;
++ } else if(strcmp(argv[0], "-Xpb") == 0) {
++ int pb;
++
++ if(argc < 2) {
++ fprintf(stderr, "%s: -Xpb missing pb\n", comp_name);
++ goto failed;
++ }
++
++ pb = atoi(argv[1]);
++
++ if (pb < LZMA_OPT_PB_MIN || pb > LZMA_OPT_PB_MAX) {
++ fprintf(stderr, "%s: -Xbp invalid value\n", comp_name);
++ goto failed;
++ }
++ options.pb = pb;
++ return 1;
++ } else if(strcmp(argv[0], "-Xfb") == 0) {
++ int fb;
++
++ if(argc < 2) {
++ fprintf(stderr, "%s: -Xfb missing fb\n", comp_name);
++ goto failed;
++ }
++
++ fb = atoi(argv[1]);
++
++ if (fb < LZMA_OPT_FB_MIN || fb > LZMA_OPT_FB_MAX) {
++ fprintf(stderr, "%s: -Xfb invalid value\n", comp_name);
++ goto failed;
++ }
++ options.fb = fb;
++ return 1;
++ } else if(strcmp(argv[0], "-Xdict-size") == 0) {
++ char *b;
++ float size;
++
++ if(argc < 2) {
++ fprintf(stderr, "%s: -Xdict-size missing dict-size\n", comp_name);
++ goto failed;
++ }
++
++ size = strtof(argv[1], &b);
++ if(*b == '%') {
++ if(size <= 0 || size > 100) {
++ fprintf(stderr, "%s: -Xdict-size percentage "
++ "should be 0 < dict-size <= 100\n", comp_name);
++ goto failed;
++ }
++
++ lzma_dict_percent = size;
++ options.dict_size = 0;
++ } else {
++ if((float) ((int) size) != size) {
++ fprintf(stderr, "%s: -Xdict-size can't be "
++ "fractional unless a percentage of the"
++ " block size\n", comp_name);
++ goto failed;
++ }
++
++ lzma_dict_percent = 0;
++ options.dict_size = (int) size;
++
++ if(*b == 'k' || *b == 'K')
++ options.dict_size *= 1024;
++ else if(*b == 'm' || *b == 'M')
++ options.dict_size *= 1024 * 1024;
++ else if(*b != '\0') {
++ fprintf(stderr, "%s: -Xdict-size invalid "
++ "dict-size\n", comp_name);
++ goto failed;
++ }
++ }
++
++ return 1;
++ }
++
++ return -1;
++
++failed:
++ return -2;
++
++}
++
++int lzma_xz_options_post(int block_size, int lzmaver)
++{
++ const char *comp_name = lzmaver_str[lzmaver];
++ /*
++ * if -Xdict-size has been specified use this to compute the datablock
++ * dictionary size
++ */
++ if(options.dict_size || lzma_dict_percent) {
++ int dict_size_min = (lzmaver == 1 ? 4096 : 8192);
++ int n;
++
++ if(options.dict_size) {
++ if(options.dict_size > block_size) {
++ fprintf(stderr, "%s: -Xdict-size is larger than"
++ " block_size\n", comp_name);
++ goto failed;
++ }
++ } else
++ options.dict_size = block_size * lzma_dict_percent / 100;
++
++ if(options.dict_size < dict_size_min) {
++ fprintf(stderr, "%s: -Xdict-size should be %i bytes "
++ "or larger\n", comp_name, dict_size_min);
++ goto failed;
++ }
++
++ /*
++ * dictionary_size must be storable in xz header as either
++ * 2^n or as 2^n+2^(n+1)
++ */
++ n = ffs(options.dict_size) - 1;
++ if(options.dict_size != (1 << n) &&
++ options.dict_size != ((1 << n) + (1 << (n + 1)))) {
++ fprintf(stderr, "%s: -Xdict-size is an unsupported "
++ "value, dict-size must be storable in %s "
++ "header\n", comp_name, comp_name);
++ fprintf(stderr, "as either 2^n or as 2^n+2^(n+1). "
++ "Example dict-sizes are 75%%, 50%%, 37.5%%, "
++ "25%%,\n");
++ fprintf(stderr, "or 32K, 16K, 8K etc.\n");
++ goto failed;
++ }
++
++ } else
++ /* No -Xdict-size specified, use defaults */
++ options.dict_size = block_size;
++
++ return 0;
++
++failed:
++ return -1;
++}
++
++static struct lzma_opts lzma_comp_opts;
++
++void *lzma_xz_dump_options(int block_size, int *size, int flags)
++{
++ /* No need to store default options */
++ if (options.preset == 6 &&
++ options.extreme == 0 &&
++ options.lc == LZMA_OPT_LC_DEFAULT &&
++ options.lp == LZMA_OPT_LC_DEFAULT &&
++ options.pb == LZMA_OPT_PB_DEFAULT &&
++ options.fb == 0 &&
++ options.dict_size == block_size &&
++ flags == 0)
++ return NULL;
++
++ *size = sizeof(struct lzma_opts);
++
++ lzma_comp_opts.flags |= flags;
++
++ if (options.extreme)
++ lzma_comp_opts.flags |= LZMA_OPT_EXTREME;
++
++ lzma_comp_opts.flags |= ((options.preset << LZMA_OPT_PRE_OFF) & LZMA_OPT_PRE_MASK);
++
++ lzma_comp_opts.bit_opts =
++ ((options.lc << LZMA_OPT_LC_OFF) & LZMA_OPT_LC_MASK) |
++ ((options.lp << LZMA_OPT_LP_OFF) & LZMA_OPT_LP_MASK) |
++ ((options.pb << LZMA_OPT_PB_OFF) & LZMA_OPT_PB_MASK);
++ lzma_comp_opts.fb = options.fb;
++ lzma_comp_opts.dict_size = options.dict_size;
++
++ SQUASHFS_INSWAP_LZMA_COMP_OPTS(&lzma_comp_opts);
++
++ return &lzma_comp_opts;
++}
++
++int lzma_xz_extract_options(int block_size, void *buffer, int size, int lzmaver)
++{
++ if (size == 0) {
++ /* default options */
++ options.preset = 6;
++ options.extreme = 0;
++ options.lc = LZMA_OPT_LC_DEFAULT;
++ options.lp = LZMA_OPT_LC_DEFAULT;
++ options.pb = LZMA_OPT_PB_DEFAULT;
++ options.fb = LZMA_OPT_FB_DEFAULT;
++ options.dict_size = block_size;
++ options.flags = 0;
++ } else {
++ struct lzma_opts *comp_opts = buffer;
++ int n;
++
++ if (size != sizeof(struct lzma_opts))
++ goto failed;
++
++ SQUASHFS_INSWAP_LZMA_COMP_OPTS(comp_opts);
++
++ options.flags = comp_opts->flags & LZMA_OPT_FLT_MASK;
++ options.preset = (comp_opts->flags & LZMA_OPT_PRE_MASK) >> LZMA_OPT_PRE_OFF;
++ options.extreme = !!(comp_opts->flags & LZMA_OPT_EXTREME);
++
++ options.lc = (comp_opts->bit_opts & LZMA_OPT_LC_MASK) >> LZMA_OPT_LC_OFF;
++ options.lp = (comp_opts->bit_opts & LZMA_OPT_LP_MASK) >> LZMA_OPT_LP_OFF;
++ options.pb = (comp_opts->bit_opts & LZMA_OPT_PB_MASK) >> LZMA_OPT_PB_OFF;
++ options.fb = comp_opts->fb;
++ options.dict_size = comp_opts->dict_size;
++
++ /* check that the LZMA bit options are in range */
++ if (options.lc < LZMA_OPT_LC_MIN || options.lc > LZMA_OPT_LC_MAX ||
++ options.lp < LZMA_OPT_LP_MIN || options.lp > LZMA_OPT_LP_MAX ||
++ options.pb < LZMA_OPT_PB_MIN || options.pb > LZMA_OPT_PB_MAX ||
++ options.fb < LZMA_OPT_FB_MIN || options.fb > LZMA_OPT_FB_MAX)
++ goto failed;
++
++ /*
++ * check that the dictionary size seems correct - the dictionary
++ * size should 2^n or 2^n+2^(n+1)
++ */
++ n = ffs(options.dict_size) - 1;
++ if(options.dict_size != (1 << n) &&
++ options.dict_size != ((1 << n) + (1 << (n + 1))))
++ goto failed;
++
++ }
++
++ return 0;
++
++failed:
++ fprintf(stderr, "%s: error reading stored compressor options from "
++ "filesystem!\n", lzmaver_str[lzmaver]);
++ return -1;
++}
++
++void lzma_xz_usage(int lzmaver)
++{
++ fprintf(stderr, "\t -Xpreset <preset>\n");
++ fprintf(stderr, "\t\tcompression preset (0-9, default 6)\n");
++ fprintf(stderr, "\t -Xe\n");
++ fprintf(stderr, "\t\tTry to improve compression ratio by using more ");
++ fprintf(stderr, "CPU time.\n");
++ fprintf(stderr, "\t -Xlc <lc>\n");
++ fprintf(stderr, "\t\tNumber of literal context bits (0-4, default 3)\n");
++ fprintf(stderr, "\t -Xlp <lp>\n");
++ fprintf(stderr, "\t\tNumber of literal position bits (0-4, default 0)\n");
++ fprintf(stderr, "\t -Xpb <pb>\n");
++ fprintf(stderr, "\t\tNumber of position bits (0-4, default 2)\n");
++ fprintf(stderr, "\t -Xnice <nice>\n");
++ fprintf(stderr, "\t\tNice length of a match (5-273, default 64)\n");
++ fprintf(stderr, "\t -Xdict-size <dict-size>\n");
++ fprintf(stderr, "\t\tUse <dict-size> as the %s dictionary size. The",
++ lzmaver == LZMA_OPT_LZMA ? "LZMA" : "XZ");
++ fprintf(stderr, " dictionary size\n\t\tcan be specified as a");
++ fprintf(stderr, " percentage of the block size, or as an\n\t\t");
++ fprintf(stderr, "absolute value. The dictionary size must be less");
++ fprintf(stderr, " than or equal\n\t\tto the block size and %d bytes",
++ lzmaver == LZMA_OPT_LZMA ? 4096 : 8192);
++ fprintf(stderr, " or larger. It must also be\n\t\tstorable in the lzma");
++ fprintf(stderr, " header as either 2^n or as 2^n+2^(n+1).\n\t\t");
++ fprintf(stderr, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or");
++ fprintf(stderr, " 32K, 16K, 8K\n\t\tetc.\n");
++
++}
+--- a/squashfs-tools/lzma_xz_wrapper.c
++++ b/squashfs-tools/lzma_xz_wrapper.c
+@@ -27,6 +27,7 @@
+
+ #include "squashfs_fs.h"
+ #include "compressor.h"
++#include "lzma_xz_options.h"
+
+ #define LZMA_PROPS_SIZE 5
+ #define LZMA_UNCOMP_SIZE 8
+@@ -38,13 +39,27 @@
+ static int lzma_compress(void *dummy, void *dest, void *src, int size,
+ int block_size, int *error)
+ {
++ uint32_t preset;
+ unsigned char *d = (unsigned char *) dest;
++ struct lzma_xz_options *opts = lzma_xz_get_options();
++
+ lzma_options_lzma opt;
+ lzma_stream strm = LZMA_STREAM_INIT;
+ int res;
+
+- lzma_lzma_preset(&opt, LZMA_OPTIONS);
+- opt.dict_size = block_size;
++ preset = opts->preset;
++
++ if (opts->extreme)
++ preset |= LZMA_PRESET_EXTREME;
++
++ lzma_lzma_preset(&opt, opts->preset);
++ opt.lc = opts->lc;
++ opt.lp = opts->lp;
++ opt.pb = opts->pb;
++ if (opts->fb)
++ opt.nice_len = opts->fb;
++
++ opt.dict_size = opts->dict_size;
+
+ res = lzma_alone_encoder(&strm, &opt);
+ if(res != LZMA_OK) {
+@@ -143,13 +158,45 @@ failed:
+ return -1;
+ }
+
++static int lzma_options(char *argv[], int argc)
++{
++ return lzma_xz_options(argv, argc, LZMA_OPT_LZMA);
++}
++
++
++static int lzma_options_post(int block_size)
++{
++ return lzma_xz_options_post(block_size, LZMA_OPT_LZMA);
++}
++
++
++static void *lzma_dump_options(int block_size, int *size)
++{
++ return lzma_xz_dump_options(block_size, size, 0);
++}
++
++
++static int lzma_extract_options(int block_size, void *buffer, int size)
++{
++ return lzma_xz_extract_options(block_size, buffer, size, LZMA_OPT_LZMA);
++}
++
++
++void lzma_usage()
++{
++ lzma_xz_usage(LZMA_OPT_LZMA);
++}
++
+
+ struct compressor lzma_comp_ops = {
+ .init = NULL,
+ .compress = lzma_compress,
+ .uncompress = lzma_uncompress,
+- .options = NULL,
+- .usage = NULL,
++ .options = lzma_options,
++ .options_post = lzma_options_post,
++ .dump_options = lzma_dump_options,
++ .extract_options = lzma_extract_options,
++ .usage = lzma_usage,
+ .id = LZMA_COMPRESSION,
+ .name = "lzma",
+ .supported = 1
+--- a/squashfs-tools/xz_wrapper.h
++++ b/squashfs-tools/xz_wrapper.h
+@@ -24,25 +24,6 @@
+ *
+ */
+
+-#ifndef linux
+-#define __BYTE_ORDER BYTE_ORDER
+-#define __BIG_ENDIAN BIG_ENDIAN
+-#define __LITTLE_ENDIAN LITTLE_ENDIAN
+-#else
+-#include <endian.h>
+-#endif
+-
+-#if __BYTE_ORDER == __BIG_ENDIAN
+-extern unsigned int inswap_le32(unsigned int);
+-
+-#define SQUASHFS_INSWAP_COMP_OPTS(s) { \
+- (s)->dictionary_size = inswap_le32((s)->dictionary_size); \
+- (s)->flags = inswap_le32((s)->flags); \
+-}
+-#else
+-#define SQUASHFS_INSWAP_COMP_OPTS(s)
+-#endif
+-
+ #define MEMLIMIT (32 * 1024 * 1024)
+
+ struct bcj {
+--- a/squashfs-tools/xz_wrapper.c
++++ b/squashfs-tools/xz_wrapper.c
+@@ -30,6 +30,7 @@
+ #include "squashfs_fs.h"
+ #include "xz_wrapper.h"
+ #include "compressor.h"
++#include "lzma_xz_options.h"
+
+ static struct bcj bcj[] = {
+ { "x86", LZMA_FILTER_X86, 0 },
+@@ -41,22 +42,18 @@ static struct bcj bcj[] = {
+ { NULL, LZMA_VLI_UNKNOWN, 0 }
+ };
+
+-static struct comp_opts comp_opts;
+-
+ static int filter_count = 1;
+-static int dictionary_size = 0;
+-static float dictionary_percent = 0;
+
+
+ static int xz_options(char *argv[], int argc)
+ {
+- int i;
+- char *name;
+-
+ if(strcmp(argv[0], "-Xbcj") == 0) {
++ int i;
++ char *name;
++
+ if(argc < 2) {
+ fprintf(stderr, "xz: -Xbcj missing filter\n");
+- goto failed;
++ return -2;
+ }
+
+ name = argv[1];
+@@ -76,190 +73,50 @@ static int xz_options(char *argv[], int
+ }
+ if(bcj[i].name == NULL) {
+ fprintf(stderr, "xz: -Xbcj unrecognised "
+- "filter\n");
+- goto failed;
+- }
+- }
+-
+- return 1;
+- } else if(strcmp(argv[0], "-Xdict-size") == 0) {
+- char *b;
+- float size;
+-
+- if(argc < 2) {
+- fprintf(stderr, "xz: -Xdict-size missing dict-size\n");
+- goto failed;
+- }
+-
+- size = strtof(argv[1], &b);
+- if(*b == '%') {
+- if(size <= 0 || size > 100) {
+- fprintf(stderr, "xz: -Xdict-size percentage "
+- "should be 0 < dict-size <= 100\n");
+- goto failed;
+- }
+-
+- dictionary_percent = size;
+- dictionary_size = 0;
+- } else {
+- if((float) ((int) size) != size) {
+- fprintf(stderr, "xz: -Xdict-size can't be "
+- "fractional unless a percentage of the"
+- " block size\n");
+- goto failed;
+- }
+-
+- dictionary_percent = 0;
+- dictionary_size = (int) size;
+-
+- if(*b == 'k' || *b == 'K')
+- dictionary_size *= 1024;
+- else if(*b == 'm' || *b == 'M')
+- dictionary_size *= 1024 * 1024;
+- else if(*b != '\0') {
+- fprintf(stderr, "xz: -Xdict-size invalid "
+- "dict-size\n");
+- goto failed;
++ "filter\n");
++ return -2;
+ }
+ }
+-
+ return 1;
++ } else {
++ return lzma_xz_options(argv, argc, LZMA_OPT_XZ);
+ }
+-
+- return -1;
+-
+-failed:
+- return -2;
+ }
+
+
+ static int xz_options_post(int block_size)
+ {
+- /*
+- * if -Xdict-size has been specified use this to compute the datablock
+- * dictionary size
+- */
+- if(dictionary_size || dictionary_percent) {
+- int n;
+-
+- if(dictionary_size) {
+- if(dictionary_size > block_size) {
+- fprintf(stderr, "xz: -Xdict-size is larger than"
+- " block_size\n");
+- goto failed;
+- }
+- } else
+- dictionary_size = block_size * dictionary_percent / 100;
+-
+- if(dictionary_size < 8192) {
+- fprintf(stderr, "xz: -Xdict-size should be 8192 bytes "
+- "or larger\n");
+- goto failed;
+- }
+-
+- /*
+- * dictionary_size must be storable in xz header as either
+- * 2^n or as 2^n+2^(n+1)
+- */
+- n = ffs(dictionary_size) - 1;
+- if(dictionary_size != (1 << n) &&
+- dictionary_size != ((1 << n) + (1 << (n + 1)))) {
+- fprintf(stderr, "xz: -Xdict-size is an unsupported "
+- "value, dict-size must be storable in xz "
+- "header\n");
+- fprintf(stderr, "as either 2^n or as 2^n+2^(n+1). "
+- "Example dict-sizes are 75%%, 50%%, 37.5%%, "
+- "25%%,\n");
+- fprintf(stderr, "or 32K, 16K, 8K etc.\n");
+- goto failed;
+- }
+-
+- } else
+- /* No -Xdict-size specified, use defaults */
+- dictionary_size = block_size;
+-
+- return 0;
+-
+-failed:
+- return -1;
++ return lzma_xz_options_post(block_size, LZMA_OPT_XZ);
+ }
+
+
+ static void *xz_dump_options(int block_size, int *size)
+ {
+- int flags = 0, i;
+-
+- /*
+- * don't store compressor specific options in file system if the
+- * default options are being used - no compressor options in the
+- * file system means the default options are always assumed
+- *
+- * Defaults are:
+- * metadata dictionary size: SQUASHFS_METADATA_SIZE
+- * datablock dictionary size: block_size
+- * 1 filter
+- */
+- if(dictionary_size == block_size && filter_count == 1)
+- return NULL;
++ int i, flags = 0;
+
+ for(i = 0; bcj[i].name; i++)
+ flags |= bcj[i].selected << i;
+
+- comp_opts.dictionary_size = dictionary_size;
+- comp_opts.flags = flags;
+-
+- SQUASHFS_INSWAP_COMP_OPTS(&comp_opts);
+-
+- *size = sizeof(comp_opts);
+- return &comp_opts;
++ return lzma_xz_dump_options(block_size, size, flags);
+ }
+
+
+ static int xz_extract_options(int block_size, void *buffer, int size)
+ {
+- struct comp_opts *comp_opts = buffer;
+- int flags, i, n;
+-
+- if(size == 0) {
+- /* set defaults */
+- dictionary_size = block_size;
+- flags = 0;
+- } else {
+- /* check passed comp opts struct is of the correct length */
+- if(size != sizeof(struct comp_opts))
+- goto failed;
+-
+- SQUASHFS_INSWAP_COMP_OPTS(comp_opts);
+-
+- dictionary_size = comp_opts->dictionary_size;
+- flags = comp_opts->flags;
+-
+- /*
+- * check that the dictionary size seems correct - the dictionary
+- * size should 2^n or 2^n+2^(n+1)
+- */
+- n = ffs(dictionary_size) - 1;
+- if(dictionary_size != (1 << n) &&
+- dictionary_size != ((1 << n) + (1 << (n + 1))))
+- goto failed;
+- }
++ int ret = lzma_xz_extract_options(block_size, buffer, size, LZMA_OPT_XZ);
+
+- filter_count = 1;
+- for(i = 0; bcj[i].name; i++) {
+- if((flags >> i) & 1) {
+- bcj[i].selected = 1;
+- filter_count ++;
+- } else
+- bcj[i].selected = 0;
++ if (!ret) {
++ int i;
++ struct lzma_xz_options *opts = lzma_xz_get_options();
++ for(i = 0; bcj[i].name; i++) {
++ if((opts->flags >> i) & 1) {
++ bcj[i].selected = 1;
++ filter_count ++;
++ } else
++ bcj[i].selected = 0;
++ }
+ }
+-
+- return 0;
+-
+-failed:
+- fprintf(stderr, "xz: error reading stored compressor options from "
+- "filesystem!\n");
+-
+- return -1;
++ return ret;
+ }
+
+
+@@ -268,6 +125,7 @@ static int xz_init(void **strm, int bloc
+ int i, j, filters = datablock ? filter_count : 1;
+ struct filter *filter = malloc(filters * sizeof(struct filter));
+ struct xz_stream *stream;
++ struct lzma_xz_options *opts = lzma_xz_get_options();
+
+ if(filter == NULL)
+ goto failed;
+@@ -281,7 +139,7 @@ static int xz_init(void **strm, int bloc
+
+ memset(filter, 0, filters * sizeof(struct filter));
+
+- stream->dictionary_size = datablock ? dictionary_size :
++ stream->dictionary_size = datablock ? opts->dict_size :
+ SQUASHFS_METADATA_SIZE;
+
+ filter[0].filter[0].id = LZMA_FILTER_LZMA2;
+@@ -323,14 +181,25 @@ static int xz_compress(void *strm, void
+ lzma_ret res = 0;
+ struct xz_stream *stream = strm;
+ struct filter *selected = NULL;
++ struct lzma_xz_options *opts = lzma_xz_get_options();
+
+ stream->filter[0].buffer = dest;
+
+ for(i = 0; i < stream->filters; i++) {
++ uint32_t preset = opts->preset;
+ struct filter *filter = &stream->filter[i];
+
+- if(lzma_lzma_preset(&stream->opt, LZMA_PRESET_DEFAULT))
+- goto failed;
++ if (opts->extreme)
++ preset |= LZMA_PRESET_EXTREME;
++
++ if(lzma_lzma_preset(&stream->opt, preset))
++ goto failed;
++
++ stream->opt.lc = opts->lc;
++ stream->opt.lp = opts->lp;
++ stream->opt.pb = opts->pb;
++ if (opts->fb)
++ stream->opt.nice_len = opts->fb;
+
+ stream->opt.dict_size = stream->dictionary_size;
+
+@@ -384,22 +253,13 @@ static int xz_uncompress(void *dest, voi
+
+ void xz_usage()
+ {
++ lzma_xz_usage(LZMA_OPT_XZ);
+ fprintf(stderr, "\t -Xbcj filter1,filter2,...,filterN\n");
+ fprintf(stderr, "\t\tCompress using filter1,filter2,...,filterN in");
+ fprintf(stderr, " turn\n\t\t(in addition to no filter), and choose");
+ fprintf(stderr, " the best compression.\n");
+ fprintf(stderr, "\t\tAvailable filters: x86, arm, armthumb,");
+ fprintf(stderr, " powerpc, sparc, ia64\n");
+- fprintf(stderr, "\t -Xdict-size <dict-size>\n");
+- fprintf(stderr, "\t\tUse <dict-size> as the XZ dictionary size. The");
+- fprintf(stderr, " dictionary size\n\t\tcan be specified as a");
+- fprintf(stderr, " percentage of the block size, or as an\n\t\t");
+- fprintf(stderr, "absolute value. The dictionary size must be less");
+- fprintf(stderr, " than or equal\n\t\tto the block size and 8192 bytes");
+- fprintf(stderr, " or larger. It must also be\n\t\tstorable in the xz");
+- fprintf(stderr, " header as either 2^n or as 2^n+2^(n+1).\n\t\t");
+- fprintf(stderr, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or");
+- fprintf(stderr, " 32K, 16K, 8K\n\t\tetc.\n");
+ }
+
+
+--- a/squashfs-tools/Makefile
++++ b/squashfs-tools/Makefile
+@@ -140,6 +140,8 @@ COMPRESSORS += xz
+ endif
+
+ ifneq ($(LZMA_XZ_SUPPORT)$(XZ_SUPPORT),)
++MKSQUASHFS_OBJS += lzma_xz_options.o
++UNSQUASHFS_OBJS += lzma_xz_options.o
+ ifneq ($(LZMA_LIB),)
+ MKSQUASHFS_OBJS += $(LZMA_LIB)
+ UNSQUASHFS_OBJS += $(LZMA_LIB)
diff --git a/tools/squashfs4/patches/170-add_support_for_LZMA_MAGIC_to_unsqashfs.patch b/tools/squashfs4/patches/170-add_support_for_LZMA_MAGIC_to_unsqashfs.patch
new file mode 100644
index 0000000..ad69b19
--- /dev/null
+++ b/tools/squashfs4/patches/170-add_support_for_LZMA_MAGIC_to_unsqashfs.patch
@@ -0,0 +1,72 @@
+--- a/squashfs-tools/squashfs_fs.h
++++ b/squashfs-tools/squashfs_fs.h
+@@ -30,6 +30,13 @@
+ #define SQUASHFS_MAGIC_SWAP 0x68737173
+ #define SQUASHFS_START 0
+
++/*
++ * Squashfs + LZMA
++ */
++
++#define SQUASHFS_MAGIC_LZMA 0x71736873
++#define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371
++
+ /* size of metadata (inode and directory) blocks */
+ #define SQUASHFS_METADATA_SIZE 8192
+ #define SQUASHFS_METADATA_LOG 13
+--- a/squashfs-tools/unsquashfs.c
++++ b/squashfs-tools/unsquashfs.c
+@@ -1463,10 +1463,12 @@ int read_super(char *source)
+ */
+ read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block),
+ &sBlk_4);
+- swap = sBlk_4.s_magic != SQUASHFS_MAGIC;
++ swap = (sBlk_4.s_magic != SQUASHFS_MAGIC &&
++ sBlk_4.s_magic != SQUASHFS_MAGIC_LZMA);
+ SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk_4);
+
+- if(sBlk_4.s_magic == SQUASHFS_MAGIC && sBlk_4.s_major == 4 &&
++ if((sBlk_4.s_magic == SQUASHFS_MAGIC ||
++ sBlk_4.s_magic == SQUASHFS_MAGIC_LZMA) && sBlk_4.s_major == 4 &&
+ sBlk_4.s_minor == 0) {
+ s_ops.squashfs_opendir = squashfs_opendir_4;
+ s_ops.read_fragment = read_fragment_4;
+@@ -1479,7 +1481,11 @@ int read_super(char *source)
+ /*
+ * Check the compression type
+ */
+- comp = lookup_compressor_id(sBlk.s.compression);
++ if (sBlk_4.s_magic == SQUASHFS_MAGIC_LZMA)
++ comp = lookup_compressor("lzma");
++ else
++ comp = lookup_compressor_id(sBlk.s.compression);
++
+ return TRUE;
+ }
+
+@@ -1494,8 +1500,10 @@ int read_super(char *source)
+ * Check it is a SQUASHFS superblock
+ */
+ swap = 0;
+- if(sBlk_3.s_magic != SQUASHFS_MAGIC) {
+- if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP) {
++ if(sBlk_3.s_magic != SQUASHFS_MAGIC &&
++ sBlk_3.s_magic != SQUASHFS_MAGIC_LZMA) {
++ if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP ||
++ sBlk_3.s_magic == SQUASHFS_MAGIC_LZMA_SWAP) {
+ squashfs_super_block_3 sblk;
+ ERROR("Reading a different endian SQUASHFS filesystem "
+ "on %s\n", source);
+@@ -1573,7 +1581,11 @@ int read_super(char *source)
+ /*
+ * 1.x, 2.x and 3.x filesystems use gzip compression.
+ */
+- comp = lookup_compressor("gzip");
++ if (sBlk.s.s_magic == SQUASHFS_MAGIC_LZMA)
++ comp = lookup_compressor("lzma");
++ else
++ comp = lookup_compressor("gzip");
++
+ return TRUE;
+
+ failed_mount:
diff --git a/tools/squashfs4/patches/180-openbsd_compat.patch b/tools/squashfs4/patches/180-openbsd_compat.patch
new file mode 100644
index 0000000..6d7a857
--- /dev/null
+++ b/tools/squashfs4/patches/180-openbsd_compat.patch
@@ -0,0 +1,26 @@
+diff -Nur squashfs4.2.orig/squashfs-tools/mksquashfs.c squashfs4.2/squashfs-tools/mksquashfs.c
+--- squashfs4.2.orig/squashfs-tools/mksquashfs.c Tue Mar 5 16:20:49 2013
++++ squashfs4.2/squashfs-tools/mksquashfs.c Tue Mar 5 16:25:10 2013
+@@ -32,6 +32,9 @@
+ #include <stdio.h>
+ #include <stddef.h>
+ #include <sys/time.h>
++#if defined(__OpenBSD__)
++#include <sys/param.h>
++#endif
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+diff -Nur squashfs4.2.orig/squashfs-tools/unsquashfs.h squashfs4.2/squashfs-tools/unsquashfs.h
+--- squashfs4.2.orig/squashfs-tools/unsquashfs.h Tue Mar 5 16:20:49 2013
++++ squashfs4.2/squashfs-tools/unsquashfs.h Tue Mar 5 16:25:57 2013
+@@ -25,6 +25,9 @@
+ #define TRUE 1
+ #define FALSE 0
+ #include <stdio.h>
++#if defined(__OpenBSD__)
++#include <sys/param.h>
++#endif
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <stdlib.h>
diff --git a/tools/squashfs4/patches/190-no_nonstatic_inline.patch b/tools/squashfs4/patches/190-no_nonstatic_inline.patch
new file mode 100644
index 0000000..7b5808a
--- /dev/null
+++ b/tools/squashfs4/patches/190-no_nonstatic_inline.patch
@@ -0,0 +1,36 @@
+--- a/squashfs-tools/mksquashfs.c
++++ b/squashfs-tools/mksquashfs.c
+@@ -735,13 +735,13 @@ void cache_block_put(struct file_buffer
+ + (((char *)A) - data_cache)))
+
+
+-inline void inc_progress_bar()
++static inline void inc_progress_bar()
+ {
+ cur_uncompressed ++;
+ }
+
+
+-inline void update_progress_bar()
++static inline void update_progress_bar()
+ {
+ pthread_mutex_lock(&progress_mutex);
+ pthread_cond_signal(&progress_wait);
+@@ -749,7 +749,7 @@ inline void update_progress_bar()
+ }
+
+
+-inline void waitforthread(int i)
++static inline void waitforthread(int i)
+ {
+ TRACE("Waiting for thread %d\n", i);
+ while(thread[i] != 0)
+@@ -3358,7 +3358,7 @@ struct inode_info *lookup_inode(struct s
+ }
+
+
+-inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir,
++static inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir,
+ struct inode_info *inode_info, struct dir_info *dir)
+ {
+ if((dir->count % DIR_ENTRIES) == 0) {