Skip to content

Instantly share code, notes, and snippets.

@jkent
Created June 10, 2013 07:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkent/5747180 to your computer and use it in GitHub Desktop.
Save jkent/5747180 to your computer and use it in GitHub Desktop.
Adds support for an odd lzma image format to unsquashfs. To be used against http://sourceforge.net/projects/squashfs/files/squashfs/squashfs4.2/squashfs4.2.tar.gz
diff -Nrup squashfs-tools/compressor.c squashfs-tools/compressor.c
--- squashfs-tools/compressor.c 2011-02-11 09:49:24.000000000 -0600
+++ squashfs-tools/compressor.c 2013-06-10 02:11:35.096301000 -0500
@@ -59,6 +59,7 @@ static struct compressor xz_comp_ops = {
extern struct compressor xz_comp_ops;
#endif
+extern struct compressor special_comp_ops;
static struct compressor unknown_comp_ops = {
NULL, NULL, NULL , NULL, NULL, NULL, NULL, NULL, 0, "unknown", 0
@@ -70,6 +71,7 @@ struct compressor *compressor[] = {
&lzma_comp_ops,
&lzo_comp_ops,
&xz_comp_ops,
+ &special_comp_ops,
&unknown_comp_ops
};
diff -Nrup squashfs-tools/Makefile squashfs-tools/Makefile
--- squashfs-tools/Makefile 2011-02-28 14:04:15.000000000 -0600
+++ squashfs-tools/Makefile 2013-06-10 02:46:36.640301000 -0500
@@ -58,8 +58,8 @@ GZIP_SUPPORT = 1
# and uncomment the LZMA_SUPPORT line below.
#
#LZMA_XZ_SUPPORT = 1
-#LZMA_SUPPORT = 1
-#LZMA_DIR = ../../../../LZMA/lzma465
+LZMA_SUPPORT = 1
+LZMA_DIR = ../../lzma465
######## Specifying default compression ########
#
@@ -120,9 +120,9 @@ LZMA_OBJS = $(LZMA_DIR)/C/Alloc.o $(LZMA
$(LZMA_DIR)/C/LzmaDec.o $(LZMA_DIR)/C/LzmaEnc.o $(LZMA_DIR)/C/LzmaLib.o
INCLUDEDIR += -I$(LZMA_DIR)/C
CFLAGS += -DLZMA_SUPPORT
-MKSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS)
-UNSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS)
-COMPRESSORS += lzma
+MKSQUASHFS_OBJS += lzma_wrapper.o special_wrapper.o $(LZMA_OBJS)
+UNSQUASHFS_OBJS += lzma_wrapper.o special_wrapper.o $(LZMA_OBJS)
+COMPRESSORS += lzma special
endif
ifeq ($(LZMA_XZ_SUPPORT),1)
diff -Nrup squashfs-tools/special_wrapper.c squashfs-tools/special_wrapper.c
--- squashfs-tools/special_wrapper.c 1969-12-31 18:00:00.000000000 -0600
+++ squashfs-tools/special_wrapper.c 2013-06-10 02:30:40.624301000 -0500
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2009, 2010
+ * Phillip Lougher <phillip@lougher.demon.co.uk>
+ *
+ * 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_wrapper.c
+ *
+ * Support for LZMA1 compression using LZMA SDK (4.65 used in
+ * development, other versions may work) http://www.7-zip.org/sdk.html
+ */
+
+#include <stdlib.h>
+#include <LzmaLib.h>
+#include <zlib.h>
+
+#include "squashfs_fs.h"
+#include "compressor.h"
+
+#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8)
+
+static int gzip_init(void **strm, int block_size, int flags)
+{
+ int res;
+ z_stream *stream;
+
+ stream = *strm = malloc(sizeof(z_stream));
+ if(stream == NULL)
+ goto failed;
+
+ stream->zalloc = Z_NULL;
+ stream->zfree = Z_NULL;
+ stream->opaque = 0;
+
+ res = deflateInit(stream, 9);
+ if(res != Z_OK)
+ goto failed2;
+
+ return 0;
+
+failed2:
+ free(stream);
+failed:
+ return -1;
+}
+
+
+static int special_init(void **strm, int block_size, int flags)
+{
+ return gzip_init(strm, block_size, flags);
+}
+
+
+static int gzip_uncompress(void *d, void *s, int size, int block_size, int *error)
+{
+ int res;
+ unsigned long bytes = block_size;
+
+ res = uncompress(d, &bytes, s, size);
+
+ *error = res;
+ return res == Z_OK ? (int) bytes : -1;
+}
+
+
+static int lzma_uncompress(void *dest, void *src, int size, int block_size,
+ int *error)
+{
+ unsigned char *s = src;
+ size_t outlen, inlen = size - LZMA_HEADER_SIZE;
+ int res;
+
+ outlen = s[LZMA_PROPS_SIZE] |
+ (s[LZMA_PROPS_SIZE + 1] << 8) |
+ (s[LZMA_PROPS_SIZE + 2] << 16) |
+ (s[LZMA_PROPS_SIZE + 3] << 24);
+
+ res = LzmaUncompress(dest, &outlen, src + LZMA_HEADER_SIZE, &inlen, src,
+ LZMA_PROPS_SIZE);
+
+ *error = res;
+ return res == SZ_OK ? outlen : -1;
+}
+
+
+static int special_uncompress(void *dest, void *src, int size, int block_size,
+ int *error)
+{
+ unsigned char *s = src;
+
+ switch (s[0]) {
+ case 0x5d:
+ return lzma_uncompress(dest, src, size, block_size, error);
+ case 0x78:
+ return gzip_uncompress(dest, src, size, block_size, error);
+ default:
+ return -1;
+ }
+}
+
+
+static int special_compress(void *strm, void *dest, void *src, int size, int block_size,
+ int *error)
+{
+ *error = -1;
+ return -1;
+}
+
+
+struct compressor special_comp_ops = {
+ .init = special_init,
+ .compress = special_compress,
+ .uncompress = special_uncompress,
+ .options = NULL,
+ .usage = NULL,
+ .id = SPECIAL_COMPRESSION,
+ .name = "special",
+ .supported = 1
+};
+
diff -Nrup squashfs-tools/squashfs_fs.h squashfs-tools/squashfs_fs.h
--- squashfs-tools/squashfs_fs.h 2011-02-11 09:49:24.000000000 -0600
+++ squashfs-tools/squashfs_fs.h 2013-06-10 02:37:07.464301000 -0500
@@ -28,6 +28,8 @@
#define SQUASHFS_MINOR 0
#define SQUASHFS_MAGIC 0x73717368
#define SQUASHFS_MAGIC_SWAP 0x68737173
+#define SQUASHFS_SPECIAL_MAGIC 0x71736873
+#define SQUASHFS_SPECIAL_MAGIC_SWAP 0x73687371
#define SQUASHFS_START 0
/* size of metadata (inode and directory) blocks */
@@ -274,6 +276,7 @@ typedef long long squashfs_inode;
#define LZMA_COMPRESSION 2
#define LZO_COMPRESSION 3
#define XZ_COMPRESSION 4
+#define SPECIAL_COMPRESSION 5
struct squashfs_super_block {
unsigned int s_magic;
diff -Nrup squashfs-tools/unsquashfs.c squashfs-tools/unsquashfs.c
--- squashfs-tools/unsquashfs.c 2011-02-28 16:27:06.000000000 -0600
+++ squashfs-tools/unsquashfs.c 2013-06-10 02:41:59.740301000 -0500
@@ -44,7 +44,7 @@ struct super_block sBlk;
squashfs_operations s_ops;
struct compressor *comp;
-int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0,
+int bytes = 0, swap, special, file_count = 0, dir_count = 0, sym_count = 0,
dev_count = 0, fifo_count = 0;
char *inode_table = NULL, *directory_table = NULL;
struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536];
@@ -1491,6 +1491,7 @@ int read_super(char *source)
* Check it is a SQUASHFS superblock
*/
swap = 0;
+ special = 0;
if(sBlk_3.s_magic != SQUASHFS_MAGIC) {
if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP) {
squashfs_super_block_3 sblk;
@@ -1499,7 +1500,17 @@ int read_super(char *source)
SQUASHFS_SWAP_SUPER_BLOCK_3(&sblk, &sBlk_3);
memcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3));
swap = 1;
- } else {
+ } else if (sBlk_3.s_magic == SQUASHFS_SPECIAL_MAGIC) {
+ special = 1;
+ } else if (sBlk_3.s_magic == SQUASHFS_SPECIAL_MAGIC_SWAP) {
+ squashfs_super_block_3 sblk;
+ ERROR("Reading a different endian SQUASHFS filesystem "
+ "on %s\n", source);
+ SQUASHFS_SWAP_SUPER_BLOCK_3(&sblk, &sBlk_3);
+ memcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3));
+ swap = 1;
+ special = 1;
+ } else {
ERROR("Can't find a SQUASHFS superblock on %s\n",
source);
goto failed_mount;
@@ -1570,7 +1581,11 @@ int read_super(char *source)
/*
* 1.x, 2.x and 3.x filesystems use gzip compression.
*/
- comp = lookup_compressor("gzip");
+ if (special) {
+ comp = lookup_compressor("special");
+ } else {
+ comp = lookup_compressor("gzip");
+ }
return TRUE;
failed_mount:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment