Skip to content

Commit

Permalink
initial checkin
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher Wade authored and Christopher Wade committed Jan 9, 2013
1 parent 00e8b5a commit 0a6b3a1
Show file tree
Hide file tree
Showing 4 changed files with 615 additions and 0 deletions.
14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CC=gcc
CFLAGS=-Wall
OBJ=rcfs.o lzo1x_decompress.o

%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)

rcfs: $(OBJ)
$(CC) $^ -o $@ $(CFLAGS) $(LDFLAGS)

.PHONY: clean

clean:
rm -rf rcfs *.o
288 changes: 288 additions & 0 deletions lzo1x_decompress.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
/*
* LZO1X Decompressor from MiniLZO
*
* Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <[email protected]>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
* Changed for kernel use by:
* Nitin Gupta <[email protected]>
* Richard Purdie <[email protected]>
*/

#include <stdio.h>
#include <sys/types.h>

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;

int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, unsigned char *out, size_t *out_len);

static inline u16 get_unaligned_be16(const u8 *p)
{
return p[0] << 8 | p[1];
}

static inline u16 get_unaligned_le16(const u8 *p)
{
return p[0] | p[1] << 8;
}

static inline u32 get_unaligned_be32(const u8 *p)
{
return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
}


#define get_unaligned(ptr) \
({ \
struct __attribute__((packed)) { \
typeof(*(ptr)) __v; \
} *__p = (void *) (ptr); \
__p->__v; \
})

#define put_unaligned(val, ptr) \
do { \
struct __attribute__((packed)) { \
typeof(*(ptr)) __v; \
} *__p = (void *) (ptr); \
__p->__v = (val); \
} while(0)

#include "lzodefs.h"

#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x))
#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op)

#define COPY4(dst, src) \
put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))

static const unsigned char lzop_magic[] = {
0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
};

#define HEADER_HAS_FILTER 0x00000800L

int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
unsigned char *out, size_t *out_len)
{
const unsigned char * const ip_end = in + in_len;
unsigned char * const op_end = out + *out_len;
const unsigned char *ip = in, *m_pos;
unsigned char *op = out;
size_t t;

*out_len = 0;

if (*ip > 17) {
t = *ip++ - 17;
if (t < 4)
goto match_next;
if (HAVE_OP(t, op_end, op))
goto output_overrun;
if (HAVE_IP(t + 1, ip_end, ip))
goto input_overrun;
do {
*op++ = *ip++;
} while (--t > 0);
goto first_literal_run;
}

while ((ip < ip_end)) {
t = *ip++;
if (t >= 16)
goto match;
if (t == 0) {
if (HAVE_IP(1, ip_end, ip))
goto input_overrun;
while (*ip == 0) {
t += 255;
ip++;
if (HAVE_IP(1, ip_end, ip))
goto input_overrun;
}
t += 15 + *ip++;
}
if (HAVE_OP(t + 3, op_end, op))
goto output_overrun;
if (HAVE_IP(t + 4, ip_end, ip))
goto input_overrun;

COPY4(op, ip);
op += 4;
ip += 4;
if (--t > 0) {
if (t >= 4) {
do {
COPY4(op, ip);
op += 4;
ip += 4;
t -= 4;
} while (t >= 4);
if (t > 0) {
do {
*op++ = *ip++;
} while (--t > 0);
}
} else {
do {
*op++ = *ip++;
} while (--t > 0);
}
}

first_literal_run:
t = *ip++;
if (t >= 16)
goto match;
m_pos = op - (1 + M2_MAX_OFFSET);
m_pos -= t >> 2;
m_pos -= *ip++ << 2;

if (HAVE_LB(m_pos, out, op))
goto lookbehind_overrun;

if (HAVE_OP(3, op_end, op))
goto output_overrun;
*op++ = *m_pos++;
*op++ = *m_pos++;
*op++ = *m_pos;

goto match_done;

do {
match:
if (t >= 64) {
m_pos = op - 1;
m_pos -= (t >> 2) & 7;
m_pos -= *ip++ << 3;
t = (t >> 5) - 1;
if (HAVE_LB(m_pos, out, op))
goto lookbehind_overrun;
if (HAVE_OP(t + 3 - 1, op_end, op))
goto output_overrun;
goto copy_match;
} else if (t >= 32) {
t &= 31;
if (t == 0) {
if (HAVE_IP(1, ip_end, ip))
goto input_overrun;
while (*ip == 0) {
t += 255;
ip++;
if (HAVE_IP(1, ip_end, ip))
goto input_overrun;
}
t += 31 + *ip++;
}
m_pos = op - 1;
m_pos -= get_unaligned_le16(ip) >> 2;
ip += 2;
} else if (t >= 16) {
m_pos = op;
m_pos -= (t & 8) << 11;

t &= 7;
if (t == 0) {
if (HAVE_IP(1, ip_end, ip))
goto input_overrun;
while (*ip == 0) {
t += 255;
ip++;
if (HAVE_IP(1, ip_end, ip))
goto input_overrun;
}
t += 7 + *ip++;
}
m_pos -= get_unaligned_le16(ip) >> 2;
ip += 2;
if (m_pos == op)
goto eof_found;
m_pos -= 0x4000;
} else {
m_pos = op - 1;
m_pos -= t >> 2;
m_pos -= *ip++ << 2;

if (HAVE_LB(m_pos, out, op))
goto lookbehind_overrun;
if (HAVE_OP(2, op_end, op))
goto output_overrun;

*op++ = *m_pos++;
*op++ = *m_pos;
goto match_done;
}

if (HAVE_LB(m_pos, out, op))
goto lookbehind_overrun;
if (HAVE_OP(t + 3 - 1, op_end, op))
goto output_overrun;

if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
COPY4(op, m_pos);
op += 4;
m_pos += 4;
t -= 4 - (3 - 1);
do {
COPY4(op, m_pos);
op += 4;
m_pos += 4;
t -= 4;
} while (t >= 4);
if (t > 0)
do {
*op++ = *m_pos++;
} while (--t > 0);
} else {
copy_match:
*op++ = *m_pos++;
*op++ = *m_pos++;
do {
*op++ = *m_pos++;
} while (--t > 0);
}
match_done:
t = ip[-2] & 3;
if (t == 0)
break;
match_next:
if (HAVE_OP(t, op_end, op))
goto output_overrun;
if (HAVE_IP(t + 1, ip_end, ip))
goto input_overrun;

*op++ = *ip++;
if (t > 1) {
*op++ = *ip++;
if (t > 2)
*op++ = *ip++;
}

t = *ip++;
} while (ip < ip_end);
}

*out_len = op - out;
return LZO_E_EOF_NOT_FOUND;

eof_found:
*out_len = op - out;
return (ip == ip_end ? LZO_E_OK :
(ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
input_overrun:
*out_len = op - out;
return LZO_E_INPUT_OVERRUN;

output_overrun:
*out_len = op - out;
return LZO_E_OUTPUT_OVERRUN;

lookbehind_overrun:
*out_len = op - out;
return LZO_E_LOOKBEHIND_OVERRUN;
}
12 changes: 12 additions & 0 deletions lzodefs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#define M2_MAX_OFFSET 0x0800

#define LZO_E_OK 0
#define LZO_E_ERROR (-1)
#define LZO_E_OUT_OF_MEMORY (-2) /* [not used right now] */
#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */
#define LZO_E_INPUT_OVERRUN (-4)
#define LZO_E_OUTPUT_OVERRUN (-5)
#define LZO_E_LOOKBEHIND_OVERRUN (-6)
#define LZO_E_EOF_NOT_FOUND (-7)
#define LZO_E_INPUT_NOT_CONSUMED (-8)
#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */
Loading

0 comments on commit 0a6b3a1

Please sign in to comment.