linux-2.6.24, linux-rt-2.6.24: squashfs-lzma-2.6.24.patch imported to oe repo
authorSteffen Sledz <sledz@dresearch.de>
Fri, 17 Apr 2009 07:09:59 +0000 (09:09 +0200)
committerSteffen Sledz <sledz@dresearch.de>
Fri, 17 Apr 2009 07:09:59 +0000 (09:09 +0200)
(former URL no longer available)

recipes/linux/linux-2.6.24/squashfs-lzma-2.6.24.patch [new file with mode: 0644]
recipes/linux/linux-rt-2.6.24/squashfs-lzma-2.6.24.patch [new file with mode: 0644]
recipes/linux/linux-rt_2.6.24.bb
recipes/linux/linux_2.6.24.bb

diff --git a/recipes/linux/linux-2.6.24/squashfs-lzma-2.6.24.patch b/recipes/linux/linux-2.6.24/squashfs-lzma-2.6.24.patch
new file mode 100644 (file)
index 0000000..fb92cbf
--- /dev/null
@@ -0,0 +1,5621 @@
+diff -urN linux-2.6.23/fs/Kconfig linux-2.6.23.sqlzma/fs/Kconfig\r
+--- linux-2.6.23/fs/Kconfig    2007-10-09 16:31:38.000000000 -0400\r
++++ linux-2.6.23.sqlzma/fs/Kconfig     2007-10-14 13:19:21.000000000 -0400\r
+@@ -1364,6 +1364,72 @@\r
\r
+         If unsure, say N.\r
\r
++config SQUASHFS\r
++      tristate "SquashFS 3.2 - Squashed file system support"\r
++      select ZLIB_INFLATE\r
++      help\r
++        Saying Y here includes support for SquashFS 3.2 (a Compressed Read-\r
++        Only File System).  Squashfs is a highly compressed read-only\r
++        filesystem for Linux.  It uses zlib and/or LZMA compression to compress\r
++        both files, inodes and directories.  Inodes in the system are very\r
++        small and all blocks are packed to minimise data overhead. Block sizes\r
++        greater than 4K are supported up to a maximum of 64K.  SquashFS 3.2\r
++        supports 64 bit filesystems and files (larger than 4GB), full uid/gid\r
++        information, hard links and timestamps.\r
++\r
++        Squashfs is intended for general read-only filesystem use, for archival\r
++        use (i.e. in cases where a .tar.gz file may be used), and in embedded\r
++        systems where low overhead is needed.  Further information and\r
++        filesystem tools are available from http://squashfs.sourceforge.net.\r
++\r
++        If you want to compile this as a module ( = code which can be\r
++        inserted in and removed from the running kernel whenever you want),\r
++        say M here and read <file:Documentation/modules.txt>.  The module\r
++        will be called squashfs.  Note that the root file system (the one\r
++        containing the directory /) cannot be compiled as a module.\r
++\r
++        If unsure, say N.\r
++\r
++config SQUASHFS_EMBEDDED\r
++\r
++      bool "Additional options for memory-constrained systems" \r
++      depends on SQUASHFS\r
++      default n\r
++      help\r
++        Saying Y here allows you to specify cache sizes and how Squashfs\r
++        allocates memory.  This is only intended for memory constrained\r
++        systems.\r
++\r
++        If unsure, say N.\r
++\r
++config SQUASHFS_FRAGMENT_CACHE_SIZE\r
++      int "Number of fragments cached" if SQUASHFS_EMBEDDED\r
++      depends on SQUASHFS\r
++      default "3"\r
++      help\r
++        By default SquashFS caches the last 3 fragments read from\r
++        the filesystem.  Increasing this amount may mean SquashFS\r
++        has to re-read fragments less often from disk, at the expense\r
++        of extra system memory.  Decreasing this amount will mean\r
++        SquashFS uses less memory at the expense of extra reads from disk.\r
++\r
++        Note there must be at least one cached fragment.  Anything\r
++        much more than three will probably not make much difference.\r
++\r
++config SQUASHFS_VMALLOC\r
++      bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED\r
++      depends on SQUASHFS\r
++      default n\r
++      help\r
++        By default SquashFS uses kmalloc to obtain fragment cache memory.\r
++        Kmalloc memory is the standard kernel allocator, but it can fail\r
++        on memory constrained systems.  Because of the way Vmalloc works,\r
++        Vmalloc can succeed when kmalloc fails.  Specifying this option\r
++        will make SquashFS always use Vmalloc to allocate the\r
++        fragment cache memory.\r
++\r
++        If unsure, say N.\r
++\r
+ config VXFS_FS\r
+       tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"\r
+       depends on BLOCK\r
+diff -urN linux-2.6.23/fs/Makefile linux-2.6.23.sqlzma/fs/Makefile\r
+--- linux-2.6.23/fs/Makefile   2007-10-09 16:31:38.000000000 -0400\r
++++ linux-2.6.23.sqlzma/fs/Makefile    2007-10-14 10:24:31.000000000 -0400\r
+@@ -72,6 +72,7 @@\r
+ obj-$(CONFIG_JBD2)            += jbd2/\r
+ obj-$(CONFIG_EXT2_FS)         += ext2/\r
+ obj-$(CONFIG_CRAMFS)          += cramfs/\r
++obj-$(CONFIG_SQUASHFS)                += squashfs/\r
+ obj-y                         += ramfs/\r
+ obj-$(CONFIG_HUGETLBFS)               += hugetlbfs/\r
+ obj-$(CONFIG_CODA_FS)         += coda/\r
+diff -urN linux-2.6.23/fs/squashfs/LzmaDecode.c linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.c\r
+--- linux-2.6.23/fs/squashfs/LzmaDecode.c      1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.c       2007-10-14 12:44:42.000000000 -0400\r
+@@ -0,0 +1,584 @@\r
++/*\r
++  LzmaDecode.c\r
++  LZMA Decoder (optimized for Speed version)\r
++  \r
++  LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)\r
++  http://www.7-zip.org/\r
++\r
++  LZMA SDK is licensed under two licenses:\r
++  1) GNU Lesser General Public License (GNU LGPL)\r
++  2) Common Public License (CPL)\r
++  It means that you can select one of these two licenses and \r
++  follow rules of that license.\r
++\r
++  SPECIAL EXCEPTION:\r
++  Igor Pavlov, as the author of this Code, expressly permits you to \r
++  statically or dynamically link your Code (or bind by name) to the \r
++  interfaces of this file without subjecting your linked Code to the \r
++  terms of the CPL or GNU LGPL. Any modifications or additions \r
++  to this file, however, are subject to the LGPL or CPL terms.\r
++*/\r
++\r
++#include "LzmaDecode.h"\r
++\r
++#define kNumTopBits 24\r
++#define kTopValue ((UInt32)1 << kNumTopBits)\r
++\r
++#define kNumBitModelTotalBits 11\r
++#define kBitModelTotal (1 << kNumBitModelTotalBits)\r
++#define kNumMoveBits 5\r
++\r
++#define RC_READ_BYTE (*Buffer++)\r
++\r
++#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \\r
++  { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}\r
++\r
++#ifdef _LZMA_IN_CB\r
++\r
++#define RC_TEST { if (Buffer == BufferLim) \\r
++  { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \\r
++  BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}\r
++\r
++#define RC_INIT Buffer = BufferLim = 0; RC_INIT2\r
++\r
++#else\r
++\r
++#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }\r
++\r
++#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2\r
++ \r
++#endif\r
++\r
++#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }\r
++\r
++#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)\r
++#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;\r
++#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;\r
++\r
++#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \\r
++  { UpdateBit0(p); mi <<= 1; A0; } else \\r
++  { UpdateBit1(p); mi = (mi + mi) + 1; A1; } \r
++  \r
++#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)               \r
++\r
++#define RangeDecoderBitTreeDecode(probs, numLevels, res) \\r
++  { int i = numLevels; res = 1; \\r
++  do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \\r
++  res -= (1 << numLevels); }\r
++\r
++\r
++#define kNumPosBitsMax 4\r
++#define kNumPosStatesMax (1 << kNumPosBitsMax)\r
++\r
++#define kLenNumLowBits 3\r
++#define kLenNumLowSymbols (1 << kLenNumLowBits)\r
++#define kLenNumMidBits 3\r
++#define kLenNumMidSymbols (1 << kLenNumMidBits)\r
++#define kLenNumHighBits 8\r
++#define kLenNumHighSymbols (1 << kLenNumHighBits)\r
++\r
++#define LenChoice 0\r
++#define LenChoice2 (LenChoice + 1)\r
++#define LenLow (LenChoice2 + 1)\r
++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))\r
++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))\r
++#define kNumLenProbs (LenHigh + kLenNumHighSymbols) \r
++\r
++\r
++#define kNumStates 12\r
++#define kNumLitStates 7\r
++\r
++#define kStartPosModelIndex 4\r
++#define kEndPosModelIndex 14\r
++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))\r
++\r
++#define kNumPosSlotBits 6\r
++#define kNumLenToPosStates 4\r
++\r
++#define kNumAlignBits 4\r
++#define kAlignTableSize (1 << kNumAlignBits)\r
++\r
++#define kMatchMinLen 2\r
++\r
++#define IsMatch 0\r
++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))\r
++#define IsRepG0 (IsRep + kNumStates)\r
++#define IsRepG1 (IsRepG0 + kNumStates)\r
++#define IsRepG2 (IsRepG1 + kNumStates)\r
++#define IsRep0Long (IsRepG2 + kNumStates)\r
++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))\r
++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))\r
++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)\r
++#define LenCoder (Align + kAlignTableSize)\r
++#define RepLenCoder (LenCoder + kNumLenProbs)\r
++#define Literal (RepLenCoder + kNumLenProbs)\r
++\r
++#if Literal != LZMA_BASE_SIZE\r
++StopCompilingDueBUG\r
++#endif\r
++\r
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)\r
++{\r
++  unsigned char prop0;\r
++  if (size < LZMA_PROPERTIES_SIZE)\r
++    return LZMA_RESULT_DATA_ERROR;\r
++  prop0 = propsData[0];\r
++  if (prop0 >= (9 * 5 * 5))\r
++    return LZMA_RESULT_DATA_ERROR;\r
++  {\r
++    for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));\r
++    for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);\r
++    propsRes->lc = prop0;\r
++    /*\r
++    unsigned char remainder = (unsigned char)(prop0 / 9);\r
++    propsRes->lc = prop0 % 9;\r
++    propsRes->pb = remainder / 5;\r
++    propsRes->lp = remainder % 5;\r
++    */\r
++  }\r
++\r
++  #ifdef _LZMA_OUT_READ\r
++  {\r
++    int i;\r
++    propsRes->DictionarySize = 0;\r
++    for (i = 0; i < 4; i++)\r
++      propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);\r
++    if (propsRes->DictionarySize == 0)\r
++      propsRes->DictionarySize = 1;\r
++  }\r
++  #endif\r
++  return LZMA_RESULT_OK;\r
++}\r
++\r
++#define kLzmaStreamWasFinishedId (-1)\r
++\r
++int LzmaDecode(CLzmaDecoderState *vs,\r
++    #ifdef _LZMA_IN_CB\r
++    ILzmaInCallback *InCallback,\r
++    #else\r
++    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,\r
++    #endif\r
++    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)\r
++{\r
++  CProb *p = vs->Probs;\r
++  SizeT nowPos = 0;\r
++  Byte previousByte = 0;\r
++  UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;\r
++  UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;\r
++  int lc = vs->Properties.lc;\r
++\r
++  #ifdef _LZMA_OUT_READ\r
++  \r
++  UInt32 Range = vs->Range;\r
++  UInt32 Code = vs->Code;\r
++  #ifdef _LZMA_IN_CB\r
++  const Byte *Buffer = vs->Buffer;\r
++  const Byte *BufferLim = vs->BufferLim;\r
++  #else\r
++  const Byte *Buffer = inStream;\r
++  const Byte *BufferLim = inStream + inSize;\r
++  #endif\r
++  int state = vs->State;\r
++  UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];\r
++  int len = vs->RemainLen;\r
++  UInt32 globalPos = vs->GlobalPos;\r
++  UInt32 distanceLimit = vs->DistanceLimit;\r
++\r
++  Byte *dictionary = vs->Dictionary;\r
++  UInt32 dictionarySize = vs->Properties.DictionarySize;\r
++  UInt32 dictionaryPos = vs->DictionaryPos;\r
++\r
++  Byte tempDictionary[4];\r
++\r
++  #ifndef _LZMA_IN_CB\r
++  *inSizeProcessed = 0;\r
++  #endif\r
++  *outSizeProcessed = 0;\r
++  if (len == kLzmaStreamWasFinishedId)\r
++    return LZMA_RESULT_OK;\r
++\r
++  if (dictionarySize == 0)\r
++  {\r
++    dictionary = tempDictionary;\r
++    dictionarySize = 1;\r
++    tempDictionary[0] = vs->TempDictionary[0];\r
++  }\r
++\r
++  if (len == kLzmaNeedInitId)\r
++  {\r
++    {\r
++      UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));\r
++      UInt32 i;\r
++      for (i = 0; i < numProbs; i++)\r
++        p[i] = kBitModelTotal >> 1; \r
++      rep0 = rep1 = rep2 = rep3 = 1;\r
++      state = 0;\r
++      globalPos = 0;\r
++      distanceLimit = 0;\r
++      dictionaryPos = 0;\r
++      dictionary[dictionarySize - 1] = 0;\r
++      #ifdef _LZMA_IN_CB\r
++      RC_INIT;\r
++      #else\r
++      RC_INIT(inStream, inSize);\r
++      #endif\r
++    }\r
++    len = 0;\r
++  }\r
++  while(len != 0 && nowPos < outSize)\r
++  {\r
++    UInt32 pos = dictionaryPos - rep0;\r
++    if (pos >= dictionarySize)\r
++      pos += dictionarySize;\r
++    outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];\r
++    if (++dictionaryPos == dictionarySize)\r
++      dictionaryPos = 0;\r
++    len--;\r
++  }\r
++  if (dictionaryPos == 0)\r
++    previousByte = dictionary[dictionarySize - 1];\r
++  else\r
++    previousByte = dictionary[dictionaryPos - 1];\r
++\r
++  #else /* if !_LZMA_OUT_READ */\r
++\r
++  int state = 0;\r
++  UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;\r
++  int len = 0;\r
++  const Byte *Buffer;\r
++  const Byte *BufferLim;\r
++  UInt32 Range;\r
++  UInt32 Code;\r
++\r
++  #ifndef _LZMA_IN_CB\r
++  *inSizeProcessed = 0;\r
++  #endif\r
++  *outSizeProcessed = 0;\r
++\r
++  {\r
++    UInt32 i;\r
++    UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));\r
++    for (i = 0; i < numProbs; i++)\r
++      p[i] = kBitModelTotal >> 1;\r
++  }\r
++  \r
++  #ifdef _LZMA_IN_CB\r
++  RC_INIT;\r
++  #else\r
++  RC_INIT(inStream, inSize);\r
++  #endif\r
++\r
++  #endif /* _LZMA_OUT_READ */\r
++\r
++  while(nowPos < outSize)\r
++  {\r
++    CProb *prob;\r
++    UInt32 bound;\r
++    int posState = (int)(\r
++        (nowPos \r
++        #ifdef _LZMA_OUT_READ\r
++        + globalPos\r
++        #endif\r
++        )\r
++        & posStateMask);\r
++\r
++    prob = p + IsMatch + (state << kNumPosBitsMax) + posState;\r
++    IfBit0(prob)\r
++    {\r
++      int symbol = 1;\r
++      UpdateBit0(prob)\r
++      prob = p + Literal + (LZMA_LIT_SIZE * \r
++        (((\r
++        (nowPos \r
++        #ifdef _LZMA_OUT_READ\r
++        + globalPos\r
++        #endif\r
++        )\r
++        & literalPosMask) << lc) + (previousByte >> (8 - lc))));\r
++\r
++      if (state >= kNumLitStates)\r
++      {\r
++        int matchByte;\r
++        #ifdef _LZMA_OUT_READ\r
++        UInt32 pos = dictionaryPos - rep0;\r
++        if (pos >= dictionarySize)\r
++          pos += dictionarySize;\r
++        matchByte = dictionary[pos];\r
++        #else\r
++        matchByte = outStream[nowPos - rep0];\r
++        #endif\r
++        do\r
++        {\r
++          int bit;\r
++          CProb *probLit;\r
++          matchByte <<= 1;\r
++          bit = (matchByte & 0x100);\r
++          probLit = prob + 0x100 + bit + symbol;\r
++          RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)\r
++        }\r
++        while (symbol < 0x100);\r
++      }\r
++      while (symbol < 0x100)\r
++      {\r
++        CProb *probLit = prob + symbol;\r
++        RC_GET_BIT(probLit, symbol)\r
++      }\r
++      previousByte = (Byte)symbol;\r
++\r
++      outStream[nowPos++] = previousByte;\r
++      #ifdef _LZMA_OUT_READ\r
++      if (distanceLimit < dictionarySize)\r
++        distanceLimit++;\r
++\r
++      dictionary[dictionaryPos] = previousByte;\r
++      if (++dictionaryPos == dictionarySize)\r
++        dictionaryPos = 0;\r
++      #endif\r
++      if (state < 4) state = 0;\r
++      else if (state < 10) state -= 3;\r
++      else state -= 6;\r
++    }\r
++    else             \r
++    {\r
++      UpdateBit1(prob);\r
++      prob = p + IsRep + state;\r
++      IfBit0(prob)\r
++      {\r
++        UpdateBit0(prob);\r
++        rep3 = rep2;\r
++        rep2 = rep1;\r
++        rep1 = rep0;\r
++        state = state < kNumLitStates ? 0 : 3;\r
++        prob = p + LenCoder;\r
++      }\r
++      else\r
++      {\r
++        UpdateBit1(prob);\r
++        prob = p + IsRepG0 + state;\r
++        IfBit0(prob)\r
++        {\r
++          UpdateBit0(prob);\r
++          prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;\r
++          IfBit0(prob)\r
++          {\r
++            #ifdef _LZMA_OUT_READ\r
++            UInt32 pos;\r
++            #endif\r
++            UpdateBit0(prob);\r
++            \r
++            #ifdef _LZMA_OUT_READ\r
++            if (distanceLimit == 0)\r
++            #else\r
++            if (nowPos == 0)\r
++            #endif\r
++              return LZMA_RESULT_DATA_ERROR;\r
++            \r
++            state = state < kNumLitStates ? 9 : 11;\r
++            #ifdef _LZMA_OUT_READ\r
++            pos = dictionaryPos - rep0;\r
++            if (pos >= dictionarySize)\r
++              pos += dictionarySize;\r
++            previousByte = dictionary[pos];\r
++            dictionary[dictionaryPos] = previousByte;\r
++            if (++dictionaryPos == dictionarySize)\r
++              dictionaryPos = 0;\r
++            #else\r
++            previousByte = outStream[nowPos - rep0];\r
++            #endif\r
++            outStream[nowPos++] = previousByte;\r
++            #ifdef _LZMA_OUT_READ\r
++            if (distanceLimit < dictionarySize)\r
++              distanceLimit++;\r
++            #endif\r
++\r
++            continue;\r
++          }\r
++          else\r
++          {\r
++            UpdateBit1(prob);\r
++          }\r
++        }\r
++        else\r
++        {\r
++          UInt32 distance;\r
++          UpdateBit1(prob);\r
++          prob = p + IsRepG1 + state;\r
++          IfBit0(prob)\r
++          {\r
++            UpdateBit0(prob);\r
++            distance = rep1;\r
++          }\r
++          else \r
++          {\r
++            UpdateBit1(prob);\r
++            prob = p + IsRepG2 + state;\r
++            IfBit0(prob)\r
++            {\r
++              UpdateBit0(prob);\r
++              distance = rep2;\r
++            }\r
++            else\r
++            {\r
++              UpdateBit1(prob);\r
++              distance = rep3;\r
++              rep3 = rep2;\r
++            }\r
++            rep2 = rep1;\r
++          }\r
++          rep1 = rep0;\r
++          rep0 = distance;\r
++        }\r
++        state = state < kNumLitStates ? 8 : 11;\r
++        prob = p + RepLenCoder;\r
++      }\r
++      {\r
++        int numBits, offset;\r
++        CProb *probLen = prob + LenChoice;\r
++        IfBit0(probLen)\r
++        {\r
++          UpdateBit0(probLen);\r
++          probLen = prob + LenLow + (posState << kLenNumLowBits);\r
++          offset = 0;\r
++          numBits = kLenNumLowBits;\r
++        }\r
++        else\r
++        {\r
++          UpdateBit1(probLen);\r
++          probLen = prob + LenChoice2;\r
++          IfBit0(probLen)\r
++          {\r
++            UpdateBit0(probLen);\r
++            probLen = prob + LenMid + (posState << kLenNumMidBits);\r
++            offset = kLenNumLowSymbols;\r
++            numBits = kLenNumMidBits;\r
++          }\r
++          else\r
++          {\r
++            UpdateBit1(probLen);\r
++            probLen = prob + LenHigh;\r
++            offset = kLenNumLowSymbols + kLenNumMidSymbols;\r
++            numBits = kLenNumHighBits;\r
++          }\r
++        }\r
++        RangeDecoderBitTreeDecode(probLen, numBits, len);\r
++        len += offset;\r
++      }\r
++\r
++      if (state < 4)\r
++      {\r
++        int posSlot;\r
++        state += kNumLitStates;\r
++        prob = p + PosSlot +\r
++            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << \r
++            kNumPosSlotBits);\r
++        RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);\r
++        if (posSlot >= kStartPosModelIndex)\r
++        {\r
++          int numDirectBits = ((posSlot >> 1) - 1);\r
++          rep0 = (2 | ((UInt32)posSlot & 1));\r
++          if (posSlot < kEndPosModelIndex)\r
++          {\r
++            rep0 <<= numDirectBits;\r
++            prob = p + SpecPos + rep0 - posSlot - 1;\r
++          }\r
++          else\r
++          {\r
++            numDirectBits -= kNumAlignBits;\r
++            do\r
++            {\r
++              RC_NORMALIZE\r
++              Range >>= 1;\r
++              rep0 <<= 1;\r
++              if (Code >= Range)\r
++              {\r
++                Code -= Range;\r
++                rep0 |= 1;\r
++              }\r
++            }\r
++            while (--numDirectBits != 0);\r
++            prob = p + Align;\r
++            rep0 <<= kNumAlignBits;\r
++            numDirectBits = kNumAlignBits;\r
++          }\r
++          {\r
++            int i = 1;\r
++            int mi = 1;\r
++            do\r
++            {\r
++              CProb *prob3 = prob + mi;\r
++              RC_GET_BIT2(prob3, mi, ; , rep0 |= i);\r
++              i <<= 1;\r
++            }\r
++            while(--numDirectBits != 0);\r
++          }\r
++        }\r
++        else\r
++          rep0 = posSlot;\r
++        if (++rep0 == (UInt32)(0))\r
++        {\r
++          /* it's for stream version */\r
++          len = kLzmaStreamWasFinishedId;\r
++          break;\r
++        }\r
++      }\r
++\r
++      len += kMatchMinLen;\r
++      #ifdef _LZMA_OUT_READ\r
++      if (rep0 > distanceLimit) \r
++      #else\r
++      if (rep0 > nowPos)\r
++      #endif\r
++        return LZMA_RESULT_DATA_ERROR;\r
++\r
++      #ifdef _LZMA_OUT_READ\r
++      if (dictionarySize - distanceLimit > (UInt32)len)\r
++        distanceLimit += len;\r
++      else\r
++        distanceLimit = dictionarySize;\r
++      #endif\r
++\r
++      do\r
++      {\r
++        #ifdef _LZMA_OUT_READ\r
++        UInt32 pos = dictionaryPos - rep0;\r
++        if (pos >= dictionarySize)\r
++          pos += dictionarySize;\r
++        previousByte = dictionary[pos];\r
++        dictionary[dictionaryPos] = previousByte;\r
++        if (++dictionaryPos == dictionarySize)\r
++          dictionaryPos = 0;\r
++        #else\r
++        previousByte = outStream[nowPos - rep0];\r
++        #endif\r
++        len--;\r
++        outStream[nowPos++] = previousByte;\r
++      }\r
++      while(len != 0 && nowPos < outSize);\r
++    }\r
++  }\r
++  RC_NORMALIZE;\r
++\r
++  #ifdef _LZMA_OUT_READ\r
++  vs->Range = Range;\r
++  vs->Code = Code;\r
++  vs->DictionaryPos = dictionaryPos;\r
++  vs->GlobalPos = globalPos + (UInt32)nowPos;\r
++  vs->DistanceLimit = distanceLimit;\r
++  vs->Reps[0] = rep0;\r
++  vs->Reps[1] = rep1;\r
++  vs->Reps[2] = rep2;\r
++  vs->Reps[3] = rep3;\r
++  vs->State = state;\r
++  vs->RemainLen = len;\r
++  vs->TempDictionary[0] = tempDictionary[0];\r
++  #endif\r
++\r
++  #ifdef _LZMA_IN_CB\r
++  vs->Buffer = Buffer;\r
++  vs->BufferLim = BufferLim;\r
++  #else\r
++  *inSizeProcessed = (SizeT)(Buffer - inStream);\r
++  #endif\r
++  *outSizeProcessed = nowPos;\r
++  return LZMA_RESULT_OK;\r
++}\r
+diff -urN linux-2.6.23/fs/squashfs/LzmaDecode.h linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.h\r
+--- linux-2.6.23/fs/squashfs/LzmaDecode.h      1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.h       2007-10-14 12:44:42.000000000 -0400\r
+@@ -0,0 +1,113 @@\r
++/* \r
++  LzmaDecode.h\r
++  LZMA Decoder interface\r
++\r
++  LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)\r
++  http://www.7-zip.org/\r
++\r
++  LZMA SDK is licensed under two licenses:\r
++  1) GNU Lesser General Public License (GNU LGPL)\r
++  2) Common Public License (CPL)\r
++  It means that you can select one of these two licenses and \r
++  follow rules of that license.\r
++\r
++  SPECIAL EXCEPTION:\r
++  Igor Pavlov, as the author of this code, expressly permits you to \r
++  statically or dynamically link your code (or bind by name) to the \r
++  interfaces of this file without subjecting your linked code to the \r
++  terms of the CPL or GNU LGPL. Any modifications or additions \r
++  to this file, however, are subject to the LGPL or CPL terms.\r
++*/\r
++\r
++#ifndef __LZMADECODE_H\r
++#define __LZMADECODE_H\r
++\r
++#include "LzmaTypes.h"\r
++\r
++/* #define _LZMA_IN_CB */\r
++/* Use callback for input data */\r
++\r
++/* #define _LZMA_OUT_READ */\r
++/* Use read function for output data */\r
++\r
++/* #define _LZMA_PROB32 */\r
++/* It can increase speed on some 32-bit CPUs, \r
++   but memory usage will be doubled in that case */\r
++\r
++/* #define _LZMA_LOC_OPT */\r
++/* Enable local speed optimizations inside code */\r
++\r
++#ifdef _LZMA_PROB32\r
++#define CProb UInt32\r
++#else\r
++#define CProb UInt16\r
++#endif\r
++\r
++#define LZMA_RESULT_OK 0\r
++#define LZMA_RESULT_DATA_ERROR 1\r
++\r
++#ifdef _LZMA_IN_CB\r
++typedef struct _ILzmaInCallback\r
++{\r
++  int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);\r
++} ILzmaInCallback;\r
++#endif\r
++\r
++#define LZMA_BASE_SIZE 1846\r
++#define LZMA_LIT_SIZE 768\r
++\r
++#define LZMA_PROPERTIES_SIZE 5\r
++\r
++typedef struct _CLzmaProperties\r
++{\r
++  int lc;\r
++  int lp;\r
++  int pb;\r
++  #ifdef _LZMA_OUT_READ\r
++  UInt32 DictionarySize;\r
++  #endif\r
++}CLzmaProperties;\r
++\r
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);\r
++\r
++#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))\r
++\r
++#define kLzmaNeedInitId (-2)\r
++\r
++typedef struct _CLzmaDecoderState\r
++{\r
++  CLzmaProperties Properties;\r
++  CProb *Probs;\r
++\r
++  #ifdef _LZMA_IN_CB\r
++  const unsigned char *Buffer;\r
++  const unsigned char *BufferLim;\r
++  #endif\r
++\r
++  #ifdef _LZMA_OUT_READ\r
++  unsigned char *Dictionary;\r
++  UInt32 Range;\r
++  UInt32 Code;\r
++  UInt32 DictionaryPos;\r
++  UInt32 GlobalPos;\r
++  UInt32 DistanceLimit;\r
++  UInt32 Reps[4];\r
++  int State;\r
++  int RemainLen;\r
++  unsigned char TempDictionary[4];\r
++  #endif\r
++} CLzmaDecoderState;\r
++\r
++#ifdef _LZMA_OUT_READ\r
++#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }\r
++#endif\r
++\r
++int LzmaDecode(CLzmaDecoderState *vs,\r
++    #ifdef _LZMA_IN_CB\r
++    ILzmaInCallback *inCallback,\r
++    #else\r
++    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,\r
++    #endif\r
++    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);\r
++\r
++#endif\r
+diff -urN linux-2.6.23/fs/squashfs/LzmaTypes.h linux-2.6.23.sqlzma/fs/squashfs/LzmaTypes.h\r
+--- linux-2.6.23/fs/squashfs/LzmaTypes.h       1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/LzmaTypes.h        2007-10-14 13:00:30.000000000 -0400\r
+@@ -0,0 +1,45 @@\r
++/* \r
++LzmaTypes.h \r
++\r
++Types for LZMA Decoder\r
++\r
++This file written and distributed to public domain by Igor Pavlov.\r
++This file is part of LZMA SDK 4.40 (2006-05-01)\r
++*/\r
++\r
++#ifndef __LZMATYPES_H\r
++#define __LZMATYPES_H\r
++\r
++#ifndef _7ZIP_BYTE_DEFINED\r
++#define _7ZIP_BYTE_DEFINED\r
++typedef unsigned char Byte;\r
++#endif \r
++\r
++#ifndef _7ZIP_UINT16_DEFINED\r
++#define _7ZIP_UINT16_DEFINED\r
++typedef unsigned short UInt16;\r
++#endif \r
++\r
++#ifndef _7ZIP_UINT32_DEFINED\r
++#define _7ZIP_UINT32_DEFINED\r
++#ifdef _LZMA_UINT32_IS_ULONG\r
++typedef unsigned long UInt32;\r
++#else\r
++typedef unsigned int UInt32;\r
++#endif\r
++#endif \r
++\r
++/* #define _LZMA_SYSTEM_SIZE_T */\r
++/* Use system's size_t. You can use it to enable 64-bit sizes supporting */\r
++\r
++#ifndef _7ZIP_SIZET_DEFINED\r
++#define _7ZIP_SIZET_DEFINED\r
++#ifdef _LZMA_SYSTEM_SIZE_T\r
++#include <stddef.h>\r
++typedef size_t SizeT;\r
++#else\r
++typedef UInt32 SizeT;\r
++#endif\r
++#endif\r
++\r
++#endif\r
+diff -urN linux-2.6.23/fs/squashfs/Makefile linux-2.6.23.sqlzma/fs/squashfs/Makefile\r
+--- linux-2.6.23/fs/squashfs/Makefile  1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/Makefile   2007-10-14 12:56:24.000000000 -0400\r
+@@ -0,0 +1,18 @@\r
++\r
++# Copyright (C) 2006 Junjiro Okajima\r
++# Copyright (C) 2006 Tomas Matejicek, slax.org\r
++\r
++# LICENSE follows the described one in lzma.txt.\r
++\r
++# $Id: Makefile,v 1.3 2006/11/27 03:54:58 jro Exp $\r
++\r
++#\r
++# Makefile for the linux squashfs routines.\r
++#\r
++\r
++obj-$(CONFIG_SQUASHFS) += unlzma.o sqlzma.o squashfs.o\r
++unlzma-y += module.o\r
++sqlzma-y += uncomp.o\r
++squashfs-y += inode.o\r
++squashfs-y += squashfs2_0.o\r
++\r
+diff -urN linux-2.6.23/fs/squashfs/inode.c linux-2.6.23.sqlzma/fs/squashfs/inode.c\r
+--- linux-2.6.23/fs/squashfs/inode.c   1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/inode.c    2007-10-14 10:29:23.000000000 -0400\r
+@@ -0,0 +1,2430 @@\r
++/*\r
++ * Squashfs - a compressed read only filesystem for Linux\r
++ *\r
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
++ * Phillip Lougher <phillip@lougher.org.uk>\r
++ *\r
++ * This program is free software; you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License\r
++ * as published by the Free Software Foundation; either version 2,\r
++ * or (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program; if not, write to the Free Software\r
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
++ *\r
++ * inode.c\r
++ */\r
++\r
++#include <linux/squashfs_fs.h>\r
++#include <linux/module.h>\r
++#include <linux/zlib.h>\r
++#include <linux/fs.h>\r
++#include <linux/squashfs_fs_sb.h>\r
++#include <linux/squashfs_fs_i.h>\r
++#include <linux/buffer_head.h>\r
++#include <linux/vfs.h>\r
++#include <linux/vmalloc.h>\r
++#include <linux/smp_lock.h>\r
++#include <linux/sched.h>\r
++#include <linux/exportfs.h>\r
++\r
++#include "squashfs.h"\r
++#include "sqlzma.h"\r
++#include "sqmagic.h"\r
++\r
++#undef KeepPreemptive\r
++#if defined(CONFIG_PREEMPT) && !defined(UnsquashNoPreempt)\r
++#define KeepPreemptive\r
++#endif\r
++\r
++struct sqlzma {\r
++#ifdef KeepPreemptive\r
++      struct mutex mtx;\r
++#endif\r
++      unsigned char read_data[SQUASHFS_FILE_MAX_SIZE];\r
++      struct sqlzma_un un;\r
++};\r
++static DEFINE_PER_CPU(struct sqlzma *, sqlzma);\r
++\r
++#define dpri(fmt, args...) /* printk("%s:%d: " fmt, __func__, __LINE__, ##args) */\r
++#define dpri_un(un)   dpri("un{%d, {%d %p}, {%d %p}, {%d %p}}\n", \\r
++                           (un)->un_lzma, (un)->un_a[0].sz, (un)->un_a[0].buf, \\r
++                           (un)->un_a[1].sz, (un)->un_a[1].buf, \\r
++                           (un)->un_a[2].sz, (un)->un_a[2].buf)\r
++\r
++static void vfs_read_inode(struct inode *i);\r
++static struct dentry *squashfs_get_parent(struct dentry *child);\r
++static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode);\r
++static int squashfs_statfs(struct dentry *, struct kstatfs *);\r
++static int squashfs_symlink_readpage(struct file *file, struct page *page);\r
++static long long read_blocklist(struct inode *inode, int index,\r
++                              int readahead_blks, char *block_list,\r
++                              unsigned short **block_p, unsigned int *bsize);\r
++static int squashfs_readpage(struct file *file, struct page *page);\r
++static int squashfs_readpage4K(struct file *file, struct page *page);\r
++static int squashfs_readdir(struct file *, void *, filldir_t);\r
++static struct dentry *squashfs_lookup(struct inode *, struct dentry *,\r
++                              struct nameidata *);\r
++static int squashfs_remount(struct super_block *s, int *flags, char *data);\r
++static void squashfs_put_super(struct super_block *);\r
++static int squashfs_get_sb(struct file_system_type *,int, const char *, void *,\r
++                              struct vfsmount *);\r
++static struct inode *squashfs_alloc_inode(struct super_block *sb);\r
++static void squashfs_destroy_inode(struct inode *inode);\r
++static int init_inodecache(void);\r
++static void destroy_inodecache(void);\r
++\r
++static struct file_system_type squashfs_fs_type = {\r
++      .owner = THIS_MODULE,\r
++      .name = "squashfs",\r
++      .get_sb = squashfs_get_sb,\r
++      .kill_sb = kill_block_super,\r
++      .fs_flags = FS_REQUIRES_DEV\r
++};\r
++\r
++static const unsigned char squashfs_filetype_table[] = {\r
++      DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK\r
++};\r
++\r
++static struct super_operations squashfs_super_ops = {\r
++      .alloc_inode = squashfs_alloc_inode,\r
++      .destroy_inode = squashfs_destroy_inode,\r
++      .statfs = squashfs_statfs,\r
++      .put_super = squashfs_put_super,\r
++      .remount_fs = squashfs_remount\r
++};\r
++\r
++static struct super_operations squashfs_export_super_ops = {\r
++      .alloc_inode = squashfs_alloc_inode,\r
++      .destroy_inode = squashfs_destroy_inode,\r
++      .statfs = squashfs_statfs,\r
++      .put_super = squashfs_put_super,\r
++      .read_inode = vfs_read_inode\r
++};\r
++\r
++static struct export_operations squashfs_export_ops = {\r
++      .get_parent = squashfs_get_parent\r
++};\r
++\r
++SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = {\r
++      .readpage = squashfs_symlink_readpage\r
++};\r
++\r
++SQSH_EXTERN const struct address_space_operations squashfs_aops = {\r
++      .readpage = squashfs_readpage\r
++};\r
++\r
++SQSH_EXTERN const struct address_space_operations squashfs_aops_4K = {\r
++      .readpage = squashfs_readpage4K\r
++};\r
++\r
++static const struct file_operations squashfs_dir_ops = {\r
++      .read = generic_read_dir,\r
++      .readdir = squashfs_readdir\r
++};\r
++\r
++SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {\r
++      .lookup = squashfs_lookup\r
++};\r
++\r
++\r
++static struct buffer_head *get_block_length(struct super_block *s,\r
++                              int *cur_index, int *offset, int *c_byte)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      unsigned short temp;\r
++      struct buffer_head *bh;\r
++\r
++      if (!(bh = sb_bread(s, *cur_index)))\r
++              goto out;\r
++\r
++      if (msblk->devblksize - *offset == 1) {\r
++              if (msblk->swap)\r
++                      ((unsigned char *) &temp)[1] = *((unsigned char *)\r
++                              (bh->b_data + *offset));\r
++              else\r
++                      ((unsigned char *) &temp)[0] = *((unsigned char *)\r
++                              (bh->b_data + *offset));\r
++              brelse(bh);\r
++              if (!(bh = sb_bread(s, ++(*cur_index))))\r
++                      goto out;\r
++              if (msblk->swap)\r
++                      ((unsigned char *) &temp)[0] = *((unsigned char *)\r
++                              bh->b_data); \r
++              else\r
++                      ((unsigned char *) &temp)[1] = *((unsigned char *)\r
++                              bh->b_data); \r
++              *c_byte = temp;\r
++              *offset = 1;\r
++      } else {\r
++              if (msblk->swap) {\r
++                      ((unsigned char *) &temp)[1] = *((unsigned char *)\r
++                              (bh->b_data + *offset));\r
++                      ((unsigned char *) &temp)[0] = *((unsigned char *)\r
++                              (bh->b_data + *offset + 1)); \r
++              } else {\r
++                      ((unsigned char *) &temp)[0] = *((unsigned char *)\r
++                              (bh->b_data + *offset));\r
++                      ((unsigned char *) &temp)[1] = *((unsigned char *)\r
++                              (bh->b_data + *offset + 1)); \r
++              }\r
++              *c_byte = temp;\r
++              *offset += 2;\r
++      }\r
++\r
++      if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {\r
++              if (*offset == msblk->devblksize) {\r
++                      brelse(bh);\r
++                      if (!(bh = sb_bread(s, ++(*cur_index))))\r
++                              goto out;\r
++                      *offset = 0;\r
++              }\r
++              if (*((unsigned char *) (bh->b_data + *offset)) !=\r
++                                              SQUASHFS_MARKER_BYTE) {\r
++                      ERROR("Metadata block marker corrupt @ %x\n",\r
++                                              *cur_index);\r
++                      brelse(bh);\r
++                      goto out;\r
++              }\r
++              (*offset)++;\r
++      }\r
++      return bh;\r
++\r
++out:\r
++      return NULL;\r
++}\r
++\r
++\r
++SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,\r
++                      long long index, unsigned int length,\r
++                      long long *next_index, int srclength)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>\r
++                      msblk->devblksize_log2) + 2];\r
++      unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);\r
++      unsigned int cur_index = index >> msblk->devblksize_log2;\r
++      int bytes, avail_bytes, b = 0, k = 0;\r
++      unsigned int compressed;\r
++      unsigned int c_byte = length;\r
++\r
++      if (c_byte) {\r
++              bytes = msblk->devblksize - offset;\r
++              compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);\r
++              c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);\r
++\r
++              TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed\r
++                                      ? "" : "un", (unsigned int) c_byte, srclength);\r
++\r
++              if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used)\r
++                      goto read_failure;\r
++\r
++              if (!(bh[0] = sb_getblk(s, cur_index)))\r
++                      goto block_release;\r
++\r
++              for (b = 1; bytes < c_byte; b++) {\r
++                      if (!(bh[b] = sb_getblk(s, ++cur_index)))\r
++                              goto block_release;\r
++                      bytes += msblk->devblksize;\r
++              }\r
++              ll_rw_block(READ, b, bh);\r
++      } else {\r
++              if (index < 0 || (index + 2) > sblk->bytes_used)\r
++                      goto read_failure;\r
++\r
++              if (!(bh[0] = get_block_length(s, &cur_index, &offset,\r
++                                                              &c_byte)))\r
++                      goto read_failure;\r
++\r
++              bytes = msblk->devblksize - offset;\r
++              compressed = SQUASHFS_COMPRESSED(c_byte);\r
++              c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);\r
++\r
++              TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed\r
++                                      ? "" : "un", (unsigned int) c_byte);\r
++\r
++              if (c_byte > srclength || (index + c_byte) > sblk->bytes_used)\r
++                      goto read_failure;\r
++\r
++              for (b = 1; bytes < c_byte; b++) {\r
++                      if (!(bh[b] = sb_getblk(s, ++cur_index)))\r
++                              goto block_release;\r
++                      bytes += msblk->devblksize;\r
++              }\r
++              ll_rw_block(READ, b - 1, bh + 1);\r
++      }\r
++\r
++      if (compressed) {\r
++              int zlib_err = Z_STREAM_END;\r
++              int rest, start;\r
++              enum {Src, Dst};\r
++              struct sized_buf sbuf[2];\r
++              struct sqlzma *percpu;\r
++\r
++              /*\r
++              * uncompress block\r
++              */\r
++              for (k = 0; k < b; k++) {\r
++                      wait_on_buffer(bh[k]);\r
++                      if (!buffer_uptodate(bh[k]))\r
++                              goto block_release;\r
++              }\r
++\r
++              avail_bytes = 0;\r
++              for (k = 0; !avail_bytes && k < b; k++) {\r
++                      avail_bytes = msblk->devblksize - offset;\r
++                      if (c_byte < avail_bytes)\r
++                              avail_bytes = c_byte;\r
++                      if (avail_bytes)\r
++                              break;\r
++                      offset = 0;\r
++                      brelse(bh[k]);\r
++              }\r
++              bytes = 0;\r
++              if (!avail_bytes)\r
++                      goto block_release; // nothing to be process\r
++\r
++              start = k;\r
++              /* it disables preemption */\r
++              percpu = get_cpu_var(sqlzma);\r
++#ifdef KeepPreemptive\r
++              put_cpu_var(sqlzma);\r
++              mutex_lock(&percpu->mtx);\r
++#endif\r
++\r
++              for (; k < b; k++) {\r
++                      memcpy(percpu->read_data + bytes, bh[k]->b_data + offset,\r
++                             avail_bytes);\r
++                      bytes += avail_bytes;\r
++                      offset = 0;\r
++                      brelse(bh[k]);\r
++                      avail_bytes = msblk->devblksize - offset;\r
++                      rest = c_byte - bytes;\r
++                      if (rest < avail_bytes)\r
++                              avail_bytes = rest;\r
++              }\r
++\r
++              sbuf[Src].buf = percpu->read_data;\r
++              sbuf[Src].sz = bytes;\r
++              sbuf[Dst].buf = buffer;\r
++              sbuf[Dst].sz = srclength;\r
++              dpri_un(&percpu->un);\r
++              dpri("src %d %p, dst %d %p\n", sbuf[Src].sz, sbuf[Src].buf,\r
++                   sbuf[Dst].sz, sbuf[Dst].buf);\r
++              zlib_err = sqlzma_un(&percpu->un, sbuf + Src, sbuf + Dst);\r
++              bytes = percpu->un.un_reslen;\r
++\r
++#ifdef KeepPreemptive\r
++              mutex_unlock(&percpu->mtx);\r
++#else\r
++              put_cpu_var(sqlzma);\r
++#endif\r
++              if (unlikely(zlib_err)) {\r
++                      dpri("zlib_err %d\n", zlib_err);\r
++                      goto release_mutex;\r
++              }\r
++      } else {\r
++              int i;\r
++\r
++              for(i = 0; i < b; i++) {\r
++                      wait_on_buffer(bh[i]);\r
++                      if(!buffer_uptodate(bh[i]))\r
++                              goto block_release;\r
++              }\r
++\r
++              for (bytes = 0; k < b; k++) {\r
++                      avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?\r
++                                      msblk->devblksize - offset :\r
++                                      c_byte - bytes;\r
++                      memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes);\r
++                      bytes += avail_bytes;\r
++                      offset = 0;\r
++                      brelse(bh[k]);\r
++              }\r
++      }\r
++\r
++      if (next_index)\r
++              *next_index = index + c_byte + (length ? 0 :\r
++                              (SQUASHFS_CHECK_DATA(msblk->sblk.flags)\r
++                               ? 3 : 2));\r
++      return bytes;\r
++\r
++release_mutex:\r
++      //mutex_unlock(&msblk->read_data_mutex);\r
++\r
++block_release:\r
++      for (; k < b; k++)\r
++              brelse(bh[k]);\r
++\r
++read_failure:\r
++      ERROR("sb_bread failed reading block 0x%x\n", cur_index);\r
++      return 0;\r
++}\r
++\r
++\r
++SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,\r
++                              long long block, unsigned int offset,\r
++                              int length, long long *next_block,\r
++                              unsigned int *next_offset)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      int n, i, bytes, return_length = length;\r
++      long long next_index;\r
++\r
++      TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);\r
++\r
++      while ( 1 ) {\r
++              for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) \r
++                      if (msblk->block_cache[i].block == block)\r
++                              break; \r
++              \r
++              mutex_lock(&msblk->block_cache_mutex);\r
++\r
++              if (i == SQUASHFS_CACHED_BLKS) {\r
++                      /* read inode header block */\r
++                      for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;\r
++                                      n ; n --, i = (i + 1) %\r
++                                      SQUASHFS_CACHED_BLKS)\r
++                              if (msblk->block_cache[i].block !=\r
++                                                      SQUASHFS_USED_BLK)\r
++                                      break;\r
++\r
++                      if (n == 0) {\r
++                              wait_queue_t wait;\r
++\r
++                              init_waitqueue_entry(&wait, current);\r
++                              add_wait_queue(&msblk->waitq, &wait);\r
++                              set_current_state(TASK_UNINTERRUPTIBLE);\r
++                              mutex_unlock(&msblk->block_cache_mutex);\r
++                              schedule();\r
++                              set_current_state(TASK_RUNNING);\r
++                              remove_wait_queue(&msblk->waitq, &wait);\r
++                              continue;\r
++                      }\r
++                      msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;\r
++\r
++                      if (msblk->block_cache[i].block ==\r
++                                                      SQUASHFS_INVALID_BLK) {\r
++                              if (!(msblk->block_cache[i].data =\r
++                                              kmalloc(SQUASHFS_METADATA_SIZE,\r
++                                              GFP_KERNEL))) {\r
++                                      ERROR("Failed to allocate cache"\r
++                                                      "block\n");\r
++                                      mutex_unlock(&msblk->block_cache_mutex);\r
++                                      goto out;\r
++                              }\r
++                      }\r
++      \r
++                      msblk->block_cache[i].block = SQUASHFS_USED_BLK;\r
++                      mutex_unlock(&msblk->block_cache_mutex);\r
++\r
++                      msblk->block_cache[i].length = squashfs_read_data(s,\r
++                              msblk->block_cache[i].data, block, 0, &next_index, SQUASHFS_METADATA_SIZE);\r
++                      if (msblk->block_cache[i].length == 0) {\r
++                              ERROR("Unable to read cache block [%llx:%x]\n",\r
++                                              block, offset);\r
++                              mutex_lock(&msblk->block_cache_mutex);\r
++                              msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;\r
++                              kfree(msblk->block_cache[i].data);\r
++                              wake_up(&msblk->waitq);\r
++                              mutex_unlock(&msblk->block_cache_mutex);\r
++                              goto out;\r
++                      }\r
++\r
++                      mutex_lock(&msblk->block_cache_mutex);\r
++                      wake_up(&msblk->waitq);\r
++                      msblk->block_cache[i].block = block;\r
++                      msblk->block_cache[i].next_index = next_index;\r
++                      TRACE("Read cache block [%llx:%x]\n", block, offset);\r
++              }\r
++\r
++              if (msblk->block_cache[i].block != block) {\r
++                      mutex_unlock(&msblk->block_cache_mutex);\r
++                      continue;\r
++              }\r
++\r
++              bytes = msblk->block_cache[i].length - offset;\r
++\r
++              if (bytes < 1) {\r
++                      mutex_unlock(&msblk->block_cache_mutex);\r
++                      goto out;\r
++              } else if (bytes >= length) {\r
++                      if (buffer)\r
++                              memcpy(buffer, msblk->block_cache[i].data +\r
++                                              offset, length);\r
++                      if (msblk->block_cache[i].length - offset == length) {\r
++                              *next_block = msblk->block_cache[i].next_index;\r
++                              *next_offset = 0;\r
++                      } else {\r
++                              *next_block = block;\r
++                              *next_offset = offset + length;\r
++                      }\r
++                      mutex_unlock(&msblk->block_cache_mutex);\r
++                      goto finish;\r
++              } else {\r
++                      if (buffer) {\r
++                              memcpy(buffer, msblk->block_cache[i].data +\r
++                                              offset, bytes);\r
++                              buffer += bytes;\r
++                      }\r
++                      block = msblk->block_cache[i].next_index;\r
++                      mutex_unlock(&msblk->block_cache_mutex);\r
++                      length -= bytes;\r
++                      offset = 0;\r
++              }\r
++      }\r
++\r
++finish:\r
++      return return_length;\r
++out:\r
++      return 0;\r
++}\r
++\r
++\r
++static int get_fragment_location(struct super_block *s, unsigned int fragment,\r
++                              long long *fragment_start_block,\r
++                              unsigned int *fragment_size)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      long long start_block =\r
++              msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];\r
++      int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);\r
++      struct squashfs_fragment_entry fragment_entry;\r
++\r
++      if (msblk->swap) {\r
++              struct squashfs_fragment_entry sfragment_entry;\r
++\r
++              if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,\r
++                                      start_block, offset,\r
++                                      sizeof(sfragment_entry), &start_block,\r
++                                      &offset))\r
++                      goto out;\r
++              SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);\r
++      } else\r
++              if (!squashfs_get_cached_block(s, (char *) &fragment_entry,\r
++                                      start_block, offset,\r
++                                      sizeof(fragment_entry), &start_block,\r
++                                      &offset))\r
++                      goto out;\r
++\r
++      *fragment_start_block = fragment_entry.start_block;\r
++      *fragment_size = fragment_entry.size;\r
++\r
++      return 1;\r
++\r
++out:\r
++      return 0;\r
++}\r
++\r
++\r
++SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct\r
++                                      squashfs_fragment_cache *fragment)\r
++{\r
++      mutex_lock(&msblk->fragment_mutex);\r
++      fragment->locked --;\r
++      wake_up(&msblk->fragment_wait_queue);\r
++      mutex_unlock(&msblk->fragment_mutex);\r
++}\r
++\r
++\r
++SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block\r
++                                      *s, long long start_block,\r
++                                      int length)\r
++{\r
++      int i, n;\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++\r
++      while ( 1 ) {\r
++              mutex_lock(&msblk->fragment_mutex);\r
++\r
++              for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&\r
++                              msblk->fragment[i].block != start_block; i++);\r
++\r
++              if (i == SQUASHFS_CACHED_FRAGMENTS) {\r
++                      for (i = msblk->next_fragment, n =\r
++                              SQUASHFS_CACHED_FRAGMENTS; n &&\r
++                              msblk->fragment[i].locked; n--, i = (i + 1) %\r
++                              SQUASHFS_CACHED_FRAGMENTS);\r
++\r
++                      if (n == 0) {\r
++                              wait_queue_t wait;\r
++\r
++                              init_waitqueue_entry(&wait, current);\r
++                              add_wait_queue(&msblk->fragment_wait_queue,\r
++                                                                      &wait);\r
++                              set_current_state(TASK_UNINTERRUPTIBLE);\r
++                              mutex_unlock(&msblk->fragment_mutex);\r
++                              schedule();\r
++                              set_current_state(TASK_RUNNING);\r
++                              remove_wait_queue(&msblk->fragment_wait_queue,\r
++                                                                      &wait);\r
++                              continue;\r
++                      }\r
++                      msblk->next_fragment = (msblk->next_fragment + 1) %\r
++                              SQUASHFS_CACHED_FRAGMENTS;\r
++                      \r
++                      if (msblk->fragment[i].data == NULL)\r
++                              if (!(msblk->fragment[i].data = SQUASHFS_ALLOC\r
++                                              (SQUASHFS_FILE_MAX_SIZE))) {\r
++                                      ERROR("Failed to allocate fragment "\r
++                                                      "cache block\n");\r
++                                      mutex_unlock(&msblk->fragment_mutex);\r
++                                      goto out;\r
++                              }\r
++\r
++                      msblk->fragment[i].block = SQUASHFS_INVALID_BLK;\r
++                      msblk->fragment[i].locked = 1;\r
++                      mutex_unlock(&msblk->fragment_mutex);\r
++\r
++                      if (!(msblk->fragment[i].length = squashfs_read_data(s,\r
++                                              msblk->fragment[i].data,\r
++                                              start_block, length, NULL, sblk->block_size))) {\r
++                              ERROR("Unable to read fragment cache block "\r
++                                                      "[%llx]\n", start_block);\r
++                              msblk->fragment[i].locked = 0;\r
++                              smp_mb();\r
++                              goto out;\r
++                      }\r
++\r
++                      mutex_lock(&msblk->fragment_mutex);\r
++                      msblk->fragment[i].block = start_block;\r
++                      TRACE("New fragment %d, start block %lld, locked %d\n",\r
++                                              i, msblk->fragment[i].block,\r
++                                              msblk->fragment[i].locked);\r
++                      mutex_unlock(&msblk->fragment_mutex);\r
++                      break;\r
++              }\r
++\r
++              msblk->fragment[i].locked++;\r
++              mutex_unlock(&msblk->fragment_mutex);\r
++              TRACE("Got fragment %d, start block %lld, locked %d\n", i,\r
++                                              msblk->fragment[i].block,\r
++                                              msblk->fragment[i].locked);\r
++              break;\r
++      }\r
++\r
++      return &msblk->fragment[i];\r
++\r
++out:\r
++      return NULL;\r
++}\r
++\r
++\r
++static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,\r
++              struct squashfs_base_inode_header *inodeb)\r
++{\r
++      i->i_ino = inodeb->inode_number;\r
++      i->i_mtime.tv_sec = inodeb->mtime;\r
++      i->i_atime.tv_sec = inodeb->mtime;\r
++      i->i_ctime.tv_sec = inodeb->mtime;\r
++      i->i_uid = msblk->uid[inodeb->uid];\r
++      i->i_mode = inodeb->mode;\r
++      i->i_size = 0;\r
++      if (inodeb->guid == SQUASHFS_GUIDS)\r
++              i->i_gid = i->i_uid;\r
++      else\r
++              i->i_gid = msblk->guid[inodeb->guid];\r
++}\r
++\r
++\r
++static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)];\r
++      int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1);\r
++      squashfs_inode_t inode;\r
++\r
++      TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino);\r
++\r
++      if (msblk->swap) {\r
++              squashfs_inode_t sinode;\r
++\r
++              if (!squashfs_get_cached_block(s, (char *) &sinode, start, offset,\r
++                                      sizeof(sinode), &start, &offset))\r
++                      goto out;\r
++              SQUASHFS_SWAP_INODE_T((&inode), &sinode);\r
++      } else if (!squashfs_get_cached_block(s, (char *) &inode, start, offset,\r
++                                      sizeof(inode), &start, &offset))\r
++                      goto out;\r
++\r
++      TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode);\r
++\r
++      return inode;\r
++\r
++out:\r
++      return SQUASHFS_INVALID_BLK;\r
++}\r
++      \r
++\r
++static void vfs_read_inode(struct inode *i)\r
++{\r
++      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
++      squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino);\r
++\r
++      TRACE("Entered vfs_read_inode\n");\r
++\r
++      if(inode != SQUASHFS_INVALID_BLK)\r
++              (msblk->read_inode)(i, inode);\r
++}\r
++\r
++\r
++static struct dentry *squashfs_get_parent(struct dentry *child)\r
++{\r
++      struct inode *i = child->d_inode;\r
++      struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode);\r
++      struct dentry *rv;\r
++\r
++      TRACE("Entered squashfs_get_parent\n");\r
++\r
++      if(parent == NULL) {\r
++              rv = ERR_PTR(-EACCES);\r
++              goto out;\r
++      }\r
++\r
++      rv = d_alloc_anon(parent);\r
++      if(rv == NULL)\r
++              rv = ERR_PTR(-ENOMEM);\r
++\r
++out:\r
++      return rv;\r
++}\r
++\r
++      \r
++SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct inode *i = iget_locked(s, inode_number);\r
++\r
++      TRACE("Entered squashfs_iget\n");\r
++\r
++      if(i && (i->i_state & I_NEW)) {\r
++              (msblk->read_inode)(i, inode);\r
++              unlock_new_inode(i);\r
++      }\r
++\r
++      return i;\r
++}\r
++\r
++\r
++static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode)\r
++{\r
++      struct super_block *s = i->i_sb;\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      long long block = SQUASHFS_INODE_BLK(inode) +\r
++              sblk->inode_table_start;\r
++      unsigned int offset = SQUASHFS_INODE_OFFSET(inode);\r
++      long long next_block;\r
++      unsigned int next_offset;\r
++      union squashfs_inode_header id, sid;\r
++      struct squashfs_base_inode_header *inodeb = &id.base,\r
++                                        *sinodeb = &sid.base;\r
++\r
++      TRACE("Entered squashfs_read_inode\n");\r
++\r
++      if (msblk->swap) {\r
++              if (!squashfs_get_cached_block(s, (char *) sinodeb, block,\r
++                                      offset, sizeof(*sinodeb), &next_block,\r
++                                      &next_offset))\r
++                      goto failed_read;\r
++              SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,\r
++                                      sizeof(*sinodeb));\r
++      } else\r
++              if (!squashfs_get_cached_block(s, (char *) inodeb, block,\r
++                                      offset, sizeof(*inodeb), &next_block,\r
++                                      &next_offset))\r
++                      goto failed_read;\r
++\r
++      squashfs_new_inode(msblk, i, inodeb);\r
++\r
++      switch(inodeb->inode_type) {\r
++              case SQUASHFS_FILE_TYPE: {\r
++                      unsigned int frag_size;\r
++                      long long frag_blk;\r
++                      struct squashfs_reg_inode_header *inodep = &id.reg;\r
++                      struct squashfs_reg_inode_header *sinodep = &sid.reg;\r
++                              \r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      frag_blk = SQUASHFS_INVALID_BLK;\r
++                      if (inodep->fragment != SQUASHFS_INVALID_FRAG &&\r
++                                      !get_fragment_location(s,\r
++                                      inodep->fragment, &frag_blk, &frag_size))\r
++                              goto failed_read;\r
++                              \r
++                      i->i_nlink = 1;\r
++                      i->i_size = inodep->file_size;\r
++                      i->i_fop = &generic_ro_fops;\r
++                      i->i_mode |= S_IFREG;\r
++                      i->i_blocks = ((i->i_size - 1) >> 9) + 1;\r
++                      SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;\r
++                      SQUASHFS_I(i)->u.s1.fragment_size = frag_size;\r
++                      SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->u.s1.block_list_start = next_block;\r
++                      SQUASHFS_I(i)->offset = next_offset;\r
++                      if (sblk->block_size > 4096)\r
++                              i->i_data.a_ops = &squashfs_aops;\r
++                      else\r
++                              i->i_data.a_ops = &squashfs_aops_4K;\r
++\r
++                      TRACE("File inode %x:%x, start_block %llx, "\r
++                                      "block_list_start %llx, offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->start_block, next_block,\r
++                                      next_offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_LREG_TYPE: {\r
++                      unsigned int frag_size;\r
++                      long long frag_blk;\r
++                      struct squashfs_lreg_inode_header *inodep = &id.lreg;\r
++                      struct squashfs_lreg_inode_header *sinodep = &sid.lreg;\r
++                              \r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      frag_blk = SQUASHFS_INVALID_BLK;\r
++                      if (inodep->fragment != SQUASHFS_INVALID_FRAG &&\r
++                                      !get_fragment_location(s,\r
++                                      inodep->fragment, &frag_blk, &frag_size))\r
++                              goto failed_read;\r
++                              \r
++                      i->i_nlink = inodep->nlink;\r
++                      i->i_size = inodep->file_size;\r
++                      i->i_fop = &generic_ro_fops;\r
++                      i->i_mode |= S_IFREG;\r
++                      i->i_blocks = ((i->i_size - 1) >> 9) + 1;\r
++                      SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;\r
++                      SQUASHFS_I(i)->u.s1.fragment_size = frag_size;\r
++                      SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->u.s1.block_list_start = next_block;\r
++                      SQUASHFS_I(i)->offset = next_offset;\r
++                      if (sblk->block_size > 4096)\r
++                              i->i_data.a_ops = &squashfs_aops;\r
++                      else\r
++                              i->i_data.a_ops = &squashfs_aops_4K;\r
++\r
++                      TRACE("File inode %x:%x, start_block %llx, "\r
++                                      "block_list_start %llx, offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->start_block, next_block,\r
++                                      next_offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_DIR_TYPE: {\r
++                      struct squashfs_dir_inode_header *inodep = &id.dir;\r
++                      struct squashfs_dir_inode_header *sinodep = &sid.dir;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_nlink = inodep->nlink;\r
++                      i->i_size = inodep->file_size;\r
++                      i->i_op = &squashfs_dir_inode_ops;\r
++                      i->i_fop = &squashfs_dir_ops;\r
++                      i->i_mode |= S_IFDIR;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->offset = inodep->offset;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_count = 0;\r
++                      SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;\r
++\r
++                      TRACE("Directory inode %x:%x, start_block %x, offset "\r
++                                      "%x\n", SQUASHFS_INODE_BLK(inode),\r
++                                      offset, inodep->start_block,\r
++                                      inodep->offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_LDIR_TYPE: {\r
++                      struct squashfs_ldir_inode_header *inodep = &id.ldir;\r
++                      struct squashfs_ldir_inode_header *sinodep = &sid.ldir;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,\r
++                                              sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_nlink = inodep->nlink;\r
++                      i->i_size = inodep->file_size;\r
++                      i->i_op = &squashfs_dir_inode_ops;\r
++                      i->i_fop = &squashfs_dir_ops;\r
++                      i->i_mode |= S_IFDIR;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->offset = inodep->offset;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_start = next_block;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_offset =\r
++                                                              next_offset;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_count =\r
++                                                              inodep->i_count;\r
++                      SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;\r
++\r
++                      TRACE("Long directory inode %x:%x, start_block %x, "\r
++                                      "offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->start_block, inodep->offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_SYMLINK_TYPE: {\r
++                      struct squashfs_symlink_inode_header *inodep =\r
++                                                              &id.symlink;\r
++                      struct squashfs_symlink_inode_header *sinodep =\r
++                                                              &sid.symlink;\r
++      \r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,\r
++                                                              sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_nlink = inodep->nlink;\r
++                      i->i_size = inodep->symlink_size;\r
++                      i->i_op = &page_symlink_inode_operations;\r
++                      i->i_data.a_ops = &squashfs_symlink_aops;\r
++                      i->i_mode |= S_IFLNK;\r
++                      SQUASHFS_I(i)->start_block = next_block;\r
++                      SQUASHFS_I(i)->offset = next_offset;\r
++\r
++                      TRACE("Symbolic link inode %x:%x, start_block %llx, "\r
++                                      "offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      next_block, next_offset);\r
++                      break;\r
++               }\r
++               case SQUASHFS_BLKDEV_TYPE:\r
++               case SQUASHFS_CHRDEV_TYPE: {\r
++                      struct squashfs_dev_inode_header *inodep = &id.dev;\r
++                      struct squashfs_dev_inode_header *sinodep = &sid.dev;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);\r
++                      } else  \r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_nlink = inodep->nlink;\r
++                      i->i_mode |= (inodeb->inode_type ==\r
++                                      SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :\r
++                                      S_IFBLK;\r
++                      init_special_inode(i, i->i_mode,\r
++                                      old_decode_dev(inodep->rdev));\r
++\r
++                      TRACE("Device inode %x:%x, rdev %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->rdev);\r
++                      break;\r
++               }\r
++               case SQUASHFS_FIFO_TYPE:\r
++               case SQUASHFS_SOCKET_TYPE: {\r
++                      struct squashfs_ipc_inode_header *inodep = &id.ipc;\r
++                      struct squashfs_ipc_inode_header *sinodep = &sid.ipc;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);\r
++                      } else  \r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_nlink = inodep->nlink;\r
++                      i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)\r
++                                                      ? S_IFIFO : S_IFSOCK;\r
++                      init_special_inode(i, i->i_mode, 0);\r
++                      break;\r
++               }\r
++               default:\r
++                      ERROR("Unknown inode type %d in squashfs_iget!\n",\r
++                                      inodeb->inode_type);\r
++                      goto failed_read1;\r
++      }\r
++      \r
++      return 1;\r
++\r
++failed_read:\r
++      ERROR("Unable to read inode [%llx:%x]\n", block, offset);\r
++\r
++failed_read1:\r
++      make_bad_inode(i);\r
++      return 0;\r
++}\r
++\r
++\r
++static int read_inode_lookup_table(struct super_block *s)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes);\r
++\r
++      TRACE("In read_inode_lookup_table, length %d\n", length);\r
++\r
++      /* Allocate inode lookup table */\r
++      if (!(msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate inode lookup table\n");\r
++              return 0;\r
++      }\r
++   \r
++      if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table,\r
++                      sblk->lookup_table_start, length |\r
++                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {\r
++              ERROR("unable to read inode lookup table\n");\r
++              return 0;\r
++      }\r
++\r
++      if (msblk->swap) {\r
++              int i;\r
++              long long block;\r
++\r
++              for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) {\r
++                      SQUASHFS_SWAP_LOOKUP_BLOCKS((&block),\r
++                                              &msblk->inode_lookup_table[i], 1);\r
++                      msblk->inode_lookup_table[i] = block;\r
++              }\r
++      }\r
++\r
++      return 1;\r
++}\r
++\r
++\r
++static int read_fragment_index_table(struct super_block *s)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments);\r
++\r
++      if(length == 0)\r
++              return 1;\r
++\r
++      /* Allocate fragment index table */\r
++      if (!(msblk->fragment_index = kmalloc(length, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate fragment index table\n");\r
++              return 0;\r
++      }\r
++   \r
++      if (!squashfs_read_data(s, (char *) msblk->fragment_index,\r
++                      sblk->fragment_table_start, length |\r
++                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {\r
++              ERROR("unable to read fragment index table\n");\r
++              return 0;\r
++      }\r
++\r
++      if (msblk->swap) {\r
++              int i;\r
++              long long fragment;\r
++\r
++              for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) {\r
++                      SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),\r
++                                              &msblk->fragment_index[i], 1);\r
++                      msblk->fragment_index[i] = fragment;\r
++              }\r
++      }\r
++\r
++      return 1;\r
++}\r
++\r
++\r
++static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)\r
++{\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++\r
++      msblk->read_inode = squashfs_read_inode;\r
++      msblk->read_blocklist = read_blocklist;\r
++      msblk->read_fragment_index_table = read_fragment_index_table;\r
++\r
++      if (sblk->s_major == 1) {\r
++              if (!squashfs_1_0_supported(msblk)) {\r
++                      SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "\r
++                              "are unsupported\n");\r
++                      SERROR("Please recompile with "\r
++                              "Squashfs 1.0 support enabled\n");\r
++                      return 0;\r
++              }\r
++      } else if (sblk->s_major == 2) {\r
++              if (!squashfs_2_0_supported(msblk)) {\r
++                      SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "\r
++                              "are unsupported\n");\r
++                      SERROR("Please recompile with "\r
++                              "Squashfs 2.0 support enabled\n");\r
++                      return 0;\r
++              }\r
++      } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >\r
++                      SQUASHFS_MINOR) {\r
++              SERROR("Major/Minor mismatch, trying to mount newer %d.%d "\r
++                              "filesystem\n", sblk->s_major, sblk->s_minor);\r
++              SERROR("Please update your kernel\n");\r
++              return 0;\r
++      }\r
++\r
++      return 1;\r
++}\r
++\r
++\r
++static int squashfs_fill_super(struct super_block *s, void *data, int silent)\r
++{\r
++      struct squashfs_sb_info *msblk;\r
++      struct squashfs_super_block *sblk;\r
++      int i, err;\r
++      char b[BDEVNAME_SIZE];\r
++      struct inode *root;\r
++      void *label;\r
++\r
++      TRACE("Entered squashfs_read_superblock\n");\r
++\r
++      err = -ENOMEM;\r
++      if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),\r
++                                              GFP_KERNEL))) {\r
++              ERROR("Failed to allocate superblock\n");\r
++              goto failure;\r
++      }\r
++      label = &&out_fsinfo;\r
++      memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));\r
++      msblk = s->s_fs_info;\r
++      sblk = &msblk->sblk;\r
++      \r
++      msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);\r
++      msblk->devblksize_log2 = ffz(~msblk->devblksize);\r
++\r
++      //mutex_init(&msblk->read_data_mutex);\r
++      mutex_init(&msblk->read_page_mutex);\r
++      mutex_init(&msblk->block_cache_mutex);\r
++      mutex_init(&msblk->fragment_mutex);\r
++      mutex_init(&msblk->meta_index_mutex);\r
++      \r
++      init_waitqueue_head(&msblk->waitq);\r
++      init_waitqueue_head(&msblk->fragment_wait_queue);\r
++\r
++      err = -EINVAL;\r
++      sblk->bytes_used = sizeof(struct squashfs_super_block);\r
++      if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,\r
++                                      sizeof(struct squashfs_super_block) |\r
++                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) {\r
++              SERROR("unable to read superblock\n");\r
++              goto *label;\r
++      }\r
++\r
++      /* Check it is a SQUASHFS superblock */\r
++      s->s_magic = sblk->s_magic;\r
++      msblk->swap = 0;\r
++      dpri("magic 0x%x\n", sblk->s_magic);\r
++      switch (sblk->s_magic) {\r
++              struct squashfs_super_block ssblk;\r
++\r
++      case SQUASHFS_MAGIC_SWAP:\r
++              /*FALLTHROUGH*/\r
++      case SQUASHFS_MAGIC_LZMA_SWAP:\r
++              WARNING("Mounting a different endian SQUASHFS "\r
++                      "filesystem on %s\n", bdevname(s->s_bdev, b));\r
++\r
++              SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);\r
++              memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));\r
++              msblk->swap = 1;\r
++              /*FALLTHROUGH*/\r
++      case SQUASHFS_MAGIC:\r
++      case SQUASHFS_MAGIC_LZMA:\r
++              break;\r
++      default:\r
++              SERROR("Can't find a SQUASHFS superblock on %s\n",\r
++                     bdevname(s->s_bdev, b));\r
++              goto *label;\r
++      }\r
++\r
++      {\r
++              struct sqlzma *p;\r
++              dpri("block_size %d\n", sblk->block_size);\r
++              BUG_ON(sblk->block_size > sizeof(p->read_data));\r
++      }\r
++\r
++      /* Check the MAJOR & MINOR versions */\r
++      err = -EINVAL;\r
++      if(!supported_squashfs_filesystem(msblk, silent))\r
++              goto *label;\r
++\r
++      /* Check the filesystem does not extend beyond the end of the\r
++         block device */\r
++      if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode))\r
++              goto *label;\r
++\r
++      /* Check the root inode for sanity */\r
++      if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE)\r
++              goto *label;\r
++\r
++      TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));\r
++      TRACE("Inodes are %scompressed\n",\r
++                                      SQUASHFS_UNCOMPRESSED_INODES\r
++                                      (sblk->flags) ? "un" : "");\r
++      TRACE("Data is %scompressed\n",\r
++                                      SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)\r
++                                      ? "un" : "");\r
++      TRACE("Check data is %s present in the filesystem\n",\r
++                                      SQUASHFS_CHECK_DATA(sblk->flags) ?\r
++                                      "" : "not");\r
++      TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);\r
++      TRACE("Block size %d\n", sblk->block_size);\r
++      TRACE("Number of inodes %d\n", sblk->inodes);\r
++      if (sblk->s_major > 1)\r
++              TRACE("Number of fragments %d\n", sblk->fragments);\r
++      TRACE("Number of uids %d\n", sblk->no_uids);\r
++      TRACE("Number of gids %d\n", sblk->no_guids);\r
++      TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);\r
++      TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);\r
++      if (sblk->s_major > 1)\r
++              TRACE("sblk->fragment_table_start %llx\n",\r
++                                      sblk->fragment_table_start);\r
++      TRACE("sblk->uid_start %llx\n", sblk->uid_start);\r
++\r
++      s->s_flags |= MS_RDONLY;\r
++      s->s_op = &squashfs_super_ops;\r
++\r
++      /* Init inode_table block pointer array */\r
++      err = -ENOMEM;\r
++      if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *\r
++                                      SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate block cache\n");\r
++              goto *label;\r
++      }\r
++      label = &&out_block_cache;\r
++\r
++      for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)\r
++              msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;\r
++\r
++      msblk->next_cache = 0;\r
++\r
++      /* Allocate read_page block */\r
++      if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate read_page block\n");\r
++              goto *label;\r
++      }\r
++      label = &&out_read_page;\r
++\r
++      /* Allocate uid and gid tables */\r
++      if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *\r
++                                      sizeof(unsigned int), GFP_KERNEL))) {\r
++              ERROR("Failed to allocate uid/gid table\n");\r
++              goto *label;\r
++      }\r
++      label = &&out_uid;\r
++      msblk->guid = msblk->uid + sblk->no_uids;\r
++   \r
++      dpri("swap %d\n", msblk->swap);\r
++      err = -EINVAL;\r
++      if (msblk->swap) {\r
++              unsigned int suid[sblk->no_uids + sblk->no_guids];\r
++\r
++              if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,\r
++                                      ((sblk->no_uids + sblk->no_guids) *\r
++                                       sizeof(unsigned int)) |\r
++                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {\r
++                      ERROR("unable to read uid/gid table\n");\r
++                      goto *label;\r
++              }\r
++\r
++              SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +\r
++                      sblk->no_guids), (sizeof(unsigned int) * 8));\r
++      } else\r
++              if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,\r
++                                      ((sblk->no_uids + sblk->no_guids) *\r
++                                       sizeof(unsigned int)) |\r
++                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {\r
++                      ERROR("unable to read uid/gid table\n");\r
++                      goto *label;\r
++              }\r
++\r
++\r
++      if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))\r
++              goto allocate_root;\r
++\r
++      err = -ENOMEM;\r
++      if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *\r
++                              SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate fragment block cache\n");\r
++              goto *label;\r
++      }\r
++      label = &&out_fragment;\r
++\r
++      for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {\r
++              msblk->fragment[i].locked = 0;\r
++              msblk->fragment[i].block = SQUASHFS_INVALID_BLK;\r
++              msblk->fragment[i].data = NULL;\r
++      }\r
++\r
++      msblk->next_fragment = 0;\r
++\r
++      /* Allocate and read fragment index table */\r
++      if (msblk->read_fragment_index_table(s) == 0)\r
++              goto *label;\r
++\r
++      if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK)\r
++              goto allocate_root;\r
++\r
++      /* Allocate and read inode lookup table */\r
++      if (read_inode_lookup_table(s) == 0)\r
++              goto failed_mount;\r
++\r
++      s->s_op = &squashfs_export_super_ops;\r
++      s->s_export_op = &squashfs_export_ops;\r
++\r
++allocate_root:\r
++      dpri("alloate_root\n");\r
++      root = new_inode(s);\r
++      if ((msblk->read_inode)(root, sblk->root_inode) == 0) {\r
++              iput(root);\r
++              goto failed_mount;\r
++      }\r
++      insert_inode_hash(root);\r
++\r
++      if ((s->s_root = d_alloc_root(root)) == NULL) {\r
++              ERROR("Root inode create failed\n");\r
++              iput(root);\r
++              goto failed_mount;\r
++      }\r
++\r
++      TRACE("Leaving squashfs_read_super\n");\r
++      return 0;\r
++\r
++failed_mount:\r
++      kfree(msblk->inode_lookup_table);\r
++      kfree(msblk->fragment_index);\r
++      kfree(msblk->fragment_index_2);\r
++ out_fragment:\r
++      kfree(msblk->fragment);\r
++ out_uid:\r
++      kfree(msblk->uid);\r
++ out_read_page:\r
++      kfree(msblk->read_page);\r
++ out_block_cache:\r
++      kfree(msblk->block_cache);\r
++ out_fsinfo:\r
++      kfree(s->s_fs_info);\r
++      s->s_fs_info = NULL;\r
++ failure:\r
++      return err;\r
++}\r
++\r
++\r
++static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)\r
++{\r
++      struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++\r
++      TRACE("Entered squashfs_statfs\n");\r
++\r
++      buf->f_type = sblk->s_magic;\r
++      buf->f_bsize = sblk->block_size;\r
++      buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;\r
++      buf->f_bfree = buf->f_bavail = 0;\r
++      buf->f_files = sblk->inodes;\r
++      buf->f_ffree = 0;\r
++      buf->f_namelen = SQUASHFS_NAME_LEN;\r
++\r
++      return 0;\r
++}\r
++\r
++\r
++static int squashfs_symlink_readpage(struct file *file, struct page *page)\r
++{\r
++      struct inode *inode = page->mapping->host;\r
++      int index = page->index << PAGE_CACHE_SHIFT, length, bytes;\r
++      long long block = SQUASHFS_I(inode)->start_block;\r
++      int offset = SQUASHFS_I(inode)->offset;\r
++      void *pageaddr = kmap(page);\r
++\r
++      TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "\r
++                              "%llx, offset %x\n", page->index,\r
++                              SQUASHFS_I(inode)->start_block,\r
++                              SQUASHFS_I(inode)->offset);\r
++\r
++      for (length = 0; length < index; length += bytes) {\r
++              if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,\r
++                              block, offset, PAGE_CACHE_SIZE, &block,\r
++                              &offset))) {\r
++                      ERROR("Unable to read symbolic link [%llx:%x]\n", block,\r
++                                      offset);\r
++                      goto skip_read;\r
++              }\r
++      }\r
++\r
++      if (length != index) {\r
++              ERROR("(squashfs_symlink_readpage) length != index\n");\r
++              bytes = 0;\r
++              goto skip_read;\r
++      }\r
++\r
++      bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :\r
++                                      i_size_read(inode) - length;\r
++\r
++      if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,\r
++                                      offset, bytes, &block, &offset)))\r
++              ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);\r
++\r
++skip_read:\r
++      memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);\r
++      kunmap(page);\r
++      flush_dcache_page(page);\r
++      SetPageUptodate(page);\r
++      unlock_page(page);\r
++\r
++      return 0;\r
++}\r
++\r
++\r
++struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)\r
++{\r
++      struct meta_index *meta = NULL;\r
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
++      int i;\r
++\r
++      mutex_lock(&msblk->meta_index_mutex);\r
++\r
++      TRACE("locate_meta_index: index %d, offset %d\n", index, offset);\r
++\r
++      if(msblk->meta_index == NULL)\r
++              goto not_allocated;\r
++\r
++      for (i = 0; i < SQUASHFS_META_NUMBER; i ++)\r
++              if (msblk->meta_index[i].inode_number == inode->i_ino &&\r
++                              msblk->meta_index[i].offset >= offset &&\r
++                              msblk->meta_index[i].offset <= index &&\r
++                              msblk->meta_index[i].locked == 0) {\r
++                      TRACE("locate_meta_index: entry %d, offset %d\n", i,\r
++                                      msblk->meta_index[i].offset);\r
++                      meta = &msblk->meta_index[i];\r
++                      offset = meta->offset;\r
++              }\r
++\r
++      if (meta)\r
++              meta->locked = 1;\r
++\r
++not_allocated:\r
++      mutex_unlock(&msblk->meta_index_mutex);\r
++\r
++      return meta;\r
++}\r
++\r
++\r
++struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)\r
++{\r
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
++      struct meta_index *meta = NULL;\r
++      int i;\r
++\r
++      mutex_lock(&msblk->meta_index_mutex);\r
++\r
++      TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);\r
++\r
++      if(msblk->meta_index == NULL) {\r
++              if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *\r
++                                      SQUASHFS_META_NUMBER, GFP_KERNEL))) {\r
++                      ERROR("Failed to allocate meta_index\n");\r
++                      goto failed;\r
++              }\r
++              for(i = 0; i < SQUASHFS_META_NUMBER; i++) {\r
++                      msblk->meta_index[i].inode_number = 0;\r
++                      msblk->meta_index[i].locked = 0;\r
++              }\r
++              msblk->next_meta_index = 0;\r
++      }\r
++\r
++      for(i = SQUASHFS_META_NUMBER; i &&\r
++                      msblk->meta_index[msblk->next_meta_index].locked; i --)\r
++              msblk->next_meta_index = (msblk->next_meta_index + 1) %\r
++                      SQUASHFS_META_NUMBER;\r
++\r
++      if(i == 0) {\r
++              TRACE("empty_meta_index: failed!\n");\r
++              goto failed;\r
++      }\r
++\r
++      TRACE("empty_meta_index: returned meta entry %d, %p\n",\r
++                      msblk->next_meta_index,\r
++                      &msblk->meta_index[msblk->next_meta_index]);\r
++\r
++      meta = &msblk->meta_index[msblk->next_meta_index];\r
++      msblk->next_meta_index = (msblk->next_meta_index + 1) %\r
++                      SQUASHFS_META_NUMBER;\r
++\r
++      meta->inode_number = inode->i_ino;\r
++      meta->offset = offset;\r
++      meta->skip = skip;\r
++      meta->entries = 0;\r
++      meta->locked = 1;\r
++\r
++failed:\r
++      mutex_unlock(&msblk->meta_index_mutex);\r
++      return meta;\r
++}\r
++\r
++\r
++void release_meta_index(struct inode *inode, struct meta_index *meta)\r
++{\r
++      meta->locked = 0;\r
++      smp_mb();\r
++}\r
++\r
++\r
++static int read_block_index(struct super_block *s, int blocks, char *block_list,\r
++              long long *start_block, int *offset)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      unsigned int *block_listp;\r
++      int block = 0;\r
++      \r
++      if (msblk->swap) {\r
++              char sblock_list[blocks << 2];\r
++\r
++              if (!squashfs_get_cached_block(s, sblock_list, *start_block,\r
++                              *offset, blocks << 2, start_block, offset)) {\r
++                      ERROR("Unable to read block list [%llx:%x]\n",\r
++                              *start_block, *offset);\r
++                      goto failure;\r
++              }\r
++              SQUASHFS_SWAP_INTS(((unsigned int *)block_list),\r
++                              ((unsigned int *)sblock_list), blocks);\r
++      } else\r
++              if (!squashfs_get_cached_block(s, block_list, *start_block,\r
++                              *offset, blocks << 2, start_block, offset)) {\r
++                      ERROR("Unable to read block list [%llx:%x]\n",\r
++                              *start_block, *offset);\r
++                      goto failure;\r
++              }\r
++\r
++      for (block_listp = (unsigned int *) block_list; blocks;\r
++                              block_listp++, blocks --)\r
++              block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);\r
++\r
++      return block;\r
++\r
++failure:\r
++      return -1;\r
++}\r
++\r
++\r
++#define SIZE 256\r
++\r
++static inline int calculate_skip(int blocks) {\r
++      int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);\r
++      return skip >= 7 ? 7 : skip + 1;\r
++}\r
++\r
++\r
++static int get_meta_index(struct inode *inode, int index,\r
++              long long *index_block, int *index_offset,\r
++              long long *data_block, char *block_list)\r
++{\r
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);\r
++      int offset = 0;\r
++      struct meta_index *meta;\r
++      struct meta_entry *meta_entry;\r
++      long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;\r
++      int cur_offset = SQUASHFS_I(inode)->offset;\r
++      long long cur_data_block = SQUASHFS_I(inode)->start_block;\r
++      int i;\r
++ \r
++      index /= SQUASHFS_META_INDEXES * skip;\r
++\r
++      while ( offset < index ) {\r
++              meta = locate_meta_index(inode, index, offset + 1);\r
++\r
++              if (meta == NULL) {\r
++                      if ((meta = empty_meta_index(inode, offset + 1,\r
++                                                      skip)) == NULL)\r
++                              goto all_done;\r
++              } else {\r
++                      if(meta->entries == 0)\r
++                              goto failed;\r
++                      offset = index < meta->offset + meta->entries ? index :\r
++                              meta->offset + meta->entries - 1;\r
++                      meta_entry = &meta->meta_entry[offset - meta->offset];\r
++                      cur_index_block = meta_entry->index_block + sblk->inode_table_start;\r
++                      cur_offset = meta_entry->offset;\r
++                      cur_data_block = meta_entry->data_block;\r
++                      TRACE("get_meta_index: offset %d, meta->offset %d, "\r
++                              "meta->entries %d\n", offset, meta->offset,\r
++                              meta->entries);\r
++                      TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"\r
++                              " data_block 0x%llx\n", cur_index_block,\r
++                              cur_offset, cur_data_block);\r
++              }\r
++\r
++              for (i = meta->offset + meta->entries; i <= index &&\r
++                              i < meta->offset + SQUASHFS_META_ENTRIES; i++) {\r
++                      int blocks = skip * SQUASHFS_META_INDEXES;\r
++\r
++                      while (blocks) {\r
++                              int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :\r
++                                      blocks;\r
++                              int res = read_block_index(inode->i_sb, block,\r
++                                      block_list, &cur_index_block,\r
++                                      &cur_offset);\r
++\r
++                              if (res == -1)\r
++                                      goto failed;\r
++\r
++                              cur_data_block += res;\r
++                              blocks -= block;\r
++                      }\r
++\r
++                      meta_entry = &meta->meta_entry[i - meta->offset];\r
++                      meta_entry->index_block = cur_index_block - sblk->inode_table_start;\r
++                      meta_entry->offset = cur_offset;\r
++                      meta_entry->data_block = cur_data_block;\r
++                      meta->entries ++;\r
++                      offset ++;\r
++              }\r
++\r
++              TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",\r
++                              meta->offset, meta->entries);\r
++\r
++              release_meta_index(inode, meta);\r
++      }\r
++\r
++all_done:\r
++      *index_block = cur_index_block;\r
++      *index_offset = cur_offset;\r
++      *data_block = cur_data_block;\r
++\r
++      return offset * SQUASHFS_META_INDEXES * skip;\r
++\r
++failed:\r
++      release_meta_index(inode, meta);\r
++      return -1;\r
++}\r
++\r
++\r
++static long long read_blocklist(struct inode *inode, int index,\r
++                              int readahead_blks, char *block_list,\r
++                              unsigned short **block_p, unsigned int *bsize)\r
++{\r
++      long long block_ptr;\r
++      int offset;\r
++      long long block;\r
++      int res = get_meta_index(inode, index, &block_ptr, &offset, &block,\r
++              block_list);\r
++\r
++      TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"\r
++                     " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,\r
++                     block);\r
++\r
++      if(res == -1)\r
++              goto failure;\r
++\r
++      index -= res;\r
++\r
++      while ( index ) {\r
++              int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;\r
++              int res = read_block_index(inode->i_sb, blocks, block_list,\r
++                      &block_ptr, &offset);\r
++              if (res == -1)\r
++                      goto failure;\r
++              block += res;\r
++              index -= blocks;\r
++      }\r
++\r
++      if (read_block_index(inode->i_sb, 1, block_list,\r
++                      &block_ptr, &offset) == -1)\r
++              goto failure;\r
++      *bsize = *((unsigned int *) block_list);\r
++\r
++      return block;\r
++\r
++failure:\r
++      return 0;\r
++}\r
++\r
++\r
++static int squashfs_readpage(struct file *file, struct page *page)\r
++{\r
++      struct inode *inode = page->mapping->host;\r
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      unsigned char *block_list;\r
++      long long block;\r
++      unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;\r
++      int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);\r
++      void *pageaddr;\r
++      struct squashfs_fragment_cache *fragment = NULL;\r
++      char *data_ptr = msblk->read_page;\r
++      \r
++      int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;\r
++      int start_index = page->index & ~mask;\r
++      int end_index = start_index | mask;\r
++\r
++      TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",\r
++                                      page->index,\r
++                                      SQUASHFS_I(inode)->start_block);\r
++\r
++      if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate block_list\n");\r
++              goto skip_read;\r
++      }\r
++\r
++      if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>\r
++                                      PAGE_CACHE_SHIFT))\r
++              goto skip_read;\r
++\r
++      if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK\r
++                                      || index < (i_size_read(inode) >>\r
++                                      sblk->block_log)) {\r
++              if ((block = (msblk->read_blocklist)(inode, index, 1,\r
++                                      block_list, NULL, &bsize)) == 0)\r
++                      goto skip_read;\r
++\r
++              mutex_lock(&msblk->read_page_mutex);\r
++              \r
++              if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,\r
++                                      block, bsize, NULL, sblk->block_size))) {\r
++                      ERROR("Unable to read page, block %llx, size %x\n", block,\r
++                                      bsize);\r
++                      mutex_unlock(&msblk->read_page_mutex);\r
++                      goto skip_read;\r
++              }\r
++      } else {\r
++              if ((fragment = get_cached_fragment(inode->i_sb,\r
++                                      SQUASHFS_I(inode)->\r
++                                      u.s1.fragment_start_block,\r
++                                      SQUASHFS_I(inode)->u.s1.fragment_size))\r
++                                      == NULL) {\r
++                      ERROR("Unable to read page, block %llx, size %x\n",\r
++                                      SQUASHFS_I(inode)->\r
++                                      u.s1.fragment_start_block,\r
++                                      (int) SQUASHFS_I(inode)->\r
++                                      u.s1.fragment_size);\r
++                      goto skip_read;\r
++              }\r
++              bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +\r
++                                      (i_size_read(inode) & (sblk->block_size\r
++                                      - 1));\r
++              byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;\r
++              data_ptr = fragment->data;\r
++      }\r
++\r
++      for (i = start_index; i <= end_index && byte_offset < bytes;\r
++                                      i++, byte_offset += PAGE_CACHE_SIZE) {\r
++              struct page *push_page;\r
++              int avail = (bytes - byte_offset) > PAGE_CACHE_SIZE ?\r
++                                      PAGE_CACHE_SIZE : bytes - byte_offset;\r
++\r
++              TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",\r
++                                      bytes, i, byte_offset, avail);\r
++\r
++              push_page = (i == page->index) ? page :\r
++                      grab_cache_page_nowait(page->mapping, i);\r
++\r
++              if (!push_page)\r
++                      continue;\r
++\r
++              if (PageUptodate(push_page))\r
++                      goto skip_page;\r
++\r
++              pageaddr = kmap_atomic(push_page, KM_USER0);\r
++              memcpy(pageaddr, data_ptr + byte_offset, avail);\r
++              memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);\r
++              kunmap_atomic(pageaddr, KM_USER0);\r
++              flush_dcache_page(push_page);\r
++              SetPageUptodate(push_page);\r
++skip_page:\r
++              unlock_page(push_page);\r
++              if(i != page->index)\r
++                      page_cache_release(push_page);\r
++      }\r
++\r
++      if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK\r
++                                      || index < (i_size_read(inode) >>\r
++                                      sblk->block_log))\r
++              mutex_unlock(&msblk->read_page_mutex);\r
++      else\r
++              release_cached_fragment(msblk, fragment);\r
++\r
++      kfree(block_list);\r
++      return 0;\r
++\r
++skip_read:\r
++      pageaddr = kmap_atomic(page, KM_USER0);\r
++      memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);\r
++      kunmap_atomic(pageaddr, KM_USER0);\r
++      flush_dcache_page(page);\r
++      SetPageUptodate(page);\r
++      unlock_page(page);\r
++\r
++      kfree(block_list);\r
++      return 0;\r
++}\r
++\r
++\r
++static int squashfs_readpage4K(struct file *file, struct page *page)\r
++{\r
++      struct inode *inode = page->mapping->host;\r
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      unsigned char *block_list;\r
++      long long block;\r
++      unsigned int bsize, bytes = 0;\r
++      void *pageaddr;\r
++      \r
++      TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",\r
++                                      page->index,\r
++                                      SQUASHFS_I(inode)->start_block);\r
++\r
++      if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>\r
++                                      PAGE_CACHE_SHIFT)) {\r
++              block_list = NULL;\r
++              goto skip_read;\r
++      }\r
++\r
++      if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate block_list\n");\r
++              goto skip_read;\r
++      }\r
++\r
++      if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK\r
++                                      || page->index < (i_size_read(inode) >>\r
++                                      sblk->block_log)) {\r
++              block = (msblk->read_blocklist)(inode, page->index, 1,\r
++                                      block_list, NULL, &bsize);\r
++              if(block == 0)\r
++                      goto skip_read;\r
++\r
++              mutex_lock(&msblk->read_page_mutex);\r
++              bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,\r
++                                      bsize, NULL, sblk->block_size);\r
++              if (bytes) {\r
++                      pageaddr = kmap_atomic(page, KM_USER0);\r
++                      memcpy(pageaddr, msblk->read_page, bytes);\r
++                      kunmap_atomic(pageaddr, KM_USER0);\r
++              } else\r
++                      ERROR("Unable to read page, block %llx, size %x\n",\r
++                                      block, bsize);\r
++              mutex_unlock(&msblk->read_page_mutex);\r
++      } else {\r
++              struct squashfs_fragment_cache *fragment =\r
++                      get_cached_fragment(inode->i_sb,\r
++                                      SQUASHFS_I(inode)->\r
++                                      u.s1.fragment_start_block,\r
++                                      SQUASHFS_I(inode)-> u.s1.fragment_size);\r
++              if (fragment) {\r
++                      bytes = i_size_read(inode) & (sblk->block_size - 1);\r
++                      pageaddr = kmap_atomic(page, KM_USER0);\r
++                      memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->\r
++                                      u.s1.fragment_offset, bytes);\r
++                      kunmap_atomic(pageaddr, KM_USER0);\r
++                      release_cached_fragment(msblk, fragment);\r
++              } else\r
++                      ERROR("Unable to read page, block %llx, size %x\n",\r
++                                      SQUASHFS_I(inode)->\r
++                                      u.s1.fragment_start_block, (int)\r
++                                      SQUASHFS_I(inode)-> u.s1.fragment_size);\r
++      }\r
++\r
++skip_read:\r
++      pageaddr = kmap_atomic(page, KM_USER0);\r
++      memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);\r
++      kunmap_atomic(pageaddr, KM_USER0);\r
++      flush_dcache_page(page);\r
++      SetPageUptodate(page);\r
++      unlock_page(page);\r
++\r
++      kfree(block_list);\r
++      return 0;\r
++}\r
++\r
++\r
++static int get_dir_index_using_offset(struct super_block *s, long long \r
++                              *next_block, unsigned int *next_offset,\r
++                              long long index_start,\r
++                              unsigned int index_offset, int i_count,\r
++                              long long f_pos)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      int i, length = 0;\r
++      struct squashfs_dir_index index;\r
++\r
++      TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",\r
++                                      i_count, (unsigned int) f_pos);\r
++\r
++      f_pos =- 3;\r
++      if (f_pos == 0)\r
++              goto finish;\r
++\r
++      for (i = 0; i < i_count; i++) {\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_index sindex;\r
++                      squashfs_get_cached_block(s, (char *) &sindex,\r
++                                      index_start, index_offset,\r
++                                      sizeof(sindex), &index_start,\r
++                                      &index_offset);\r
++                      SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);\r
++              } else\r
++                      squashfs_get_cached_block(s, (char *) &index,\r
++                                      index_start, index_offset,\r
++                                      sizeof(index), &index_start,\r
++                                      &index_offset);\r
++\r
++              if (index.index > f_pos)\r
++                      break;\r
++\r
++              squashfs_get_cached_block(s, NULL, index_start, index_offset,\r
++                                      index.size + 1, &index_start,\r
++                                      &index_offset);\r
++\r
++              length = index.index;\r
++              *next_block = index.start_block + sblk->directory_table_start;\r
++      }\r
++\r
++      *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;\r
++\r
++finish:\r
++      return length + 3;\r
++}\r
++\r
++\r
++static int get_dir_index_using_name(struct super_block *s, long long\r
++                              *next_block, unsigned int *next_offset,\r
++                              long long index_start,\r
++                              unsigned int index_offset, int i_count,\r
++                              const char *name, int size)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      int i, length = 0;\r
++      struct squashfs_dir_index *index;\r
++      char *str;\r
++\r
++      TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);\r
++\r
++      if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +\r
++              (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate squashfs_dir_index\n");\r
++              goto failure;\r
++      }\r
++\r
++      index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1);\r
++      strncpy(str, name, size);\r
++      str[size] = '\0';\r
++\r
++      for (i = 0; i < i_count; i++) {\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_index sindex;\r
++                      squashfs_get_cached_block(s, (char *) &sindex,\r
++                                      index_start, index_offset,\r
++                                      sizeof(sindex), &index_start,\r
++                                      &index_offset);\r
++                      SQUASHFS_SWAP_DIR_INDEX(index, &sindex);\r
++              } else\r
++                      squashfs_get_cached_block(s, (char *) index,\r
++                                      index_start, index_offset,\r
++                                      sizeof(struct squashfs_dir_index),\r
++                                      &index_start, &index_offset);\r
++\r
++              squashfs_get_cached_block(s, index->name, index_start,\r
++                                      index_offset, index->size + 1,\r
++                                      &index_start, &index_offset);\r
++\r
++              index->name[index->size + 1] = '\0';\r
++\r
++              if (strcmp(index->name, str) > 0)\r
++                      break;\r
++\r
++              length = index->index;\r
++              *next_block = index->start_block + sblk->directory_table_start;\r
++      }\r
++\r
++      *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;\r
++      kfree(str);\r
++failure:\r
++      return length + 3;\r
++}\r
++\r
++              \r
++static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)\r
++{\r
++      struct inode *i = file->f_dentry->d_inode;\r
++      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      long long next_block = SQUASHFS_I(i)->start_block +\r
++              sblk->directory_table_start;\r
++      int next_offset = SQUASHFS_I(i)->offset, length = 0,\r
++              dir_count;\r
++      struct squashfs_dir_header dirh;\r
++      struct squashfs_dir_entry *dire;\r
++\r
++      TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);\r
++\r
++      if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +\r
++              SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate squashfs_dir_entry\n");\r
++              goto finish;\r
++      }\r
++\r
++      while(file->f_pos < 3) {\r
++              char *name;\r
++              int size, i_ino;\r
++\r
++              if(file->f_pos == 0) {\r
++                      name = ".";\r
++                      size = 1;\r
++                      i_ino = i->i_ino;\r
++              } else {\r
++                      name = "..";\r
++                      size = 2;\r
++                      i_ino = SQUASHFS_I(i)->u.s2.parent_inode;\r
++              }\r
++              TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",\r
++                              (unsigned int) dirent, name, size, (int)\r
++                              file->f_pos, i_ino,\r
++                              squashfs_filetype_table[1]);\r
++\r
++              if (filldir(dirent, name, size,\r
++                              file->f_pos, i_ino,\r
++                              squashfs_filetype_table[1]) < 0) {\r
++                              TRACE("Filldir returned less than 0\n");\r
++                              goto finish;\r
++              }\r
++              file->f_pos += size;\r
++      }\r
++\r
++      length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_start,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_count,\r
++                              file->f_pos);\r
++\r
++      while (length < i_size_read(i)) {\r
++              /* read directory header */\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_header sdirh;\r
++                      \r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,\r
++                                      next_block, next_offset, sizeof(sdirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(sdirh);\r
++                      SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);\r
++              } else {\r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,\r
++                                      next_block, next_offset, sizeof(dirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(dirh);\r
++              }\r
++\r
++              dir_count = dirh.count + 1;\r
++              while (dir_count--) {\r
++                      if (msblk->swap) {\r
++                              struct squashfs_dir_entry sdire;\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              &sdire, next_block, next_offset,\r
++                                              sizeof(sdire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              \r
++                              length += sizeof(sdire);\r
++                              SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);\r
++                      } else {\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              dire, next_block, next_offset,\r
++                                              sizeof(*dire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                              length += sizeof(*dire);\r
++                      }\r
++\r
++                      if (!squashfs_get_cached_block(i->i_sb, dire->name,\r
++                                              next_block, next_offset,\r
++                                              dire->size + 1, &next_block,\r
++                                              &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += dire->size + 1;\r
++\r
++                      if (file->f_pos >= length)\r
++                              continue;\r
++\r
++                      dire->name[dire->size + 1] = '\0';\r
++\r
++                      TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",\r
++                                      (unsigned int) dirent, dire->name,\r
++                                      dire->size + 1, (int) file->f_pos,\r
++                                      dirh.start_block, dire->offset,\r
++                                      dirh.inode_number + dire->inode_number,\r
++                                      squashfs_filetype_table[dire->type]);\r
++\r
++                      if (filldir(dirent, dire->name, dire->size + 1,\r
++                                      file->f_pos,\r
++                                      dirh.inode_number + dire->inode_number,\r
++                                      squashfs_filetype_table[dire->type])\r
++                                      < 0) {\r
++                              TRACE("Filldir returned less than 0\n");\r
++                              goto finish;\r
++                      }\r
++                      file->f_pos = length;\r
++              }\r
++      }\r
++\r
++finish:\r
++      kfree(dire);\r
++      return 0;\r
++\r
++failed_read:\r
++      ERROR("Unable to read directory block [%llx:%x]\n", next_block,\r
++              next_offset);\r
++      kfree(dire);\r
++      return 0;\r
++}\r
++\r
++\r
++static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,\r
++                              struct nameidata *nd)\r
++{\r
++      const unsigned char *name = dentry->d_name.name;\r
++      int len = dentry->d_name.len;\r
++      struct inode *inode = NULL;\r
++      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      long long next_block = SQUASHFS_I(i)->start_block +\r
++                              sblk->directory_table_start;\r
++      int next_offset = SQUASHFS_I(i)->offset, length = 0,\r
++                              dir_count;\r
++      struct squashfs_dir_header dirh;\r
++      struct squashfs_dir_entry *dire;\r
++\r
++      TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);\r
++\r
++      if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +\r
++              SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate squashfs_dir_entry\n");\r
++              goto exit_lookup;\r
++      }\r
++\r
++      if (len > SQUASHFS_NAME_LEN)\r
++              goto exit_lookup;\r
++\r
++      length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_start,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_count, name,\r
++                              len);\r
++\r
++      while (length < i_size_read(i)) {\r
++              /* read directory header */\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_header sdirh;\r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,\r
++                                      next_block, next_offset, sizeof(sdirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(sdirh);\r
++                      SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);\r
++              } else {\r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,\r
++                                      next_block, next_offset, sizeof(dirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(dirh);\r
++              }\r
++\r
++              dir_count = dirh.count + 1;\r
++              while (dir_count--) {\r
++                      if (msblk->swap) {\r
++                              struct squashfs_dir_entry sdire;\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              &sdire, next_block,next_offset,\r
++                                              sizeof(sdire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              \r
++                              length += sizeof(sdire);\r
++                              SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);\r
++                      } else {\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              dire, next_block,next_offset,\r
++                                              sizeof(*dire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                              length += sizeof(*dire);\r
++                      }\r
++\r
++                      if (!squashfs_get_cached_block(i->i_sb, dire->name,\r
++                                      next_block, next_offset, dire->size + 1,\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += dire->size + 1;\r
++\r
++                      if (name[0] < dire->name[0])\r
++                              goto exit_lookup;\r
++\r
++                      if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) {\r
++                              squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block,\r
++                                                              dire->offset);\r
++\r
++                              TRACE("calling squashfs_iget for directory "\r
++                                      "entry %s, inode %x:%x, %d\n", name,\r
++                                      dirh.start_block, dire->offset,\r
++                                      dirh.inode_number + dire->inode_number);\r
++\r
++                              inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number);\r
++\r
++                              goto exit_lookup;\r
++                      }\r
++              }\r
++      }\r
++\r
++exit_lookup:\r
++      kfree(dire);\r
++      if (inode)\r
++              return d_splice_alias(inode, dentry);\r
++      d_add(dentry, inode);\r
++      return ERR_PTR(0);\r
++\r
++failed_read:\r
++      ERROR("Unable to read directory block [%llx:%x]\n", next_block,\r
++              next_offset);\r
++      goto exit_lookup;\r
++}\r
++\r
++\r
++static int squashfs_remount(struct super_block *s, int *flags, char *data)\r
++{\r
++      *flags |= MS_RDONLY;\r
++      return 0;\r
++}\r
++\r
++\r
++static void squashfs_put_super(struct super_block *s)\r
++{\r
++      int i;\r
++\r
++      if (s->s_fs_info) {\r
++              struct squashfs_sb_info *sbi = s->s_fs_info;\r
++              if (sbi->block_cache)\r
++                      for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)\r
++                              if (sbi->block_cache[i].block !=\r
++                                                      SQUASHFS_INVALID_BLK)\r
++                                      kfree(sbi->block_cache[i].data);\r
++              if (sbi->fragment)\r
++                      for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) \r
++                              SQUASHFS_FREE(sbi->fragment[i].data);\r
++              kfree(sbi->fragment);\r
++              kfree(sbi->block_cache);\r
++              kfree(sbi->read_page);\r
++              kfree(sbi->uid);\r
++              kfree(sbi->fragment_index);\r
++              kfree(sbi->fragment_index_2);\r
++              kfree(sbi->meta_index);\r
++              kfree(s->s_fs_info);\r
++              s->s_fs_info = NULL;\r
++      }\r
++}\r
++\r
++\r
++static int squashfs_get_sb(struct file_system_type *fs_type, int flags,\r
++                              const char *dev_name, void *data,\r
++                              struct vfsmount *mnt)\r
++{\r
++      return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,\r
++                              mnt);\r
++}\r
++\r
++\r
++static void free_sqlzma(void)\r
++{\r
++      int cpu;\r
++      struct sqlzma *p;\r
++\r
++      for_each_online_cpu(cpu) {\r
++              p = per_cpu(sqlzma, cpu);\r
++              if (p) {\r
++#ifdef KeepPreemptive\r
++                      mutex_destroy(&p->mtx);\r
++#endif\r
++                      sqlzma_fin(&p->un);\r
++                      kfree(p);\r
++              }\r
++      }\r
++}\r
++\r
++static int __init init_squashfs_fs(void)\r
++{\r
++      struct sqlzma *p;\r
++      int cpu;\r
++      int err = init_inodecache();\r
++      if (err)\r
++              goto out;\r
++\r
++      for_each_online_cpu(cpu) {\r
++              dpri("%d: %p\n", cpu, per_cpu(sqlzma, cpu));\r
++              err = -ENOMEM;\r
++              p = kmalloc(sizeof(struct sqlzma), GFP_KERNEL);\r
++              if (p) {\r
++#ifdef KeepPreemptive\r
++                      mutex_init(&p->mtx);\r
++#endif\r
++                      err = sqlzma_init(&p->un, 1, 0);\r
++                      if (unlikely(err)) {\r
++                              ERROR("Failed to intialize uncompress workspace\n");\r
++                              break;\r
++                      }\r
++                      per_cpu(sqlzma, cpu) = p;\r
++                      err = 0;\r
++              } else\r
++                      break;\r
++      }\r
++      if (unlikely(err)) {\r
++              free_sqlzma();\r
++              goto out;\r
++      }\r
++\r
++      printk(KERN_INFO "squashfs: version 3.2-r2 (2007/01/15) "\r
++              "Phillip Lougher\n"\r
++              "squashfs: LZMA suppport for slax.org by jro\n");\r
++\r
++      if ((err = register_filesystem(&squashfs_fs_type))) {\r
++              free_sqlzma();\r
++              destroy_inodecache();\r
++      }\r
++\r
++out:\r
++      return err;\r
++}\r
++\r
++\r
++static void __exit exit_squashfs_fs(void)\r
++{\r
++      unregister_filesystem(&squashfs_fs_type);\r
++      free_sqlzma();\r
++      destroy_inodecache();\r
++}\r
++\r
++\r
++static struct kmem_cache * squashfs_inode_cachep;\r
++\r
++\r
++static struct inode *squashfs_alloc_inode(struct super_block *sb)\r
++{\r
++      struct squashfs_inode_info *ei;\r
++      ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);\r
++      if (!ei)\r
++              return NULL;\r
++      return &ei->vfs_inode;\r
++}\r
++\r
++\r
++static void squashfs_destroy_inode(struct inode *inode)\r
++{\r
++      kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));\r
++}\r
++\r
++\r
++static void init_once(struct kmem_cache * cachep, void * foo)\r
++{\r
++      struct squashfs_inode_info *ei = foo;\r
++              inode_init_once(&ei->vfs_inode);\r
++}\r
++ \r
++\r
++static int __init init_inodecache(void)\r
++{\r
++      squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",\r
++           sizeof(struct squashfs_inode_info),\r
++           0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,\r
++           init_once);\r
++      if (squashfs_inode_cachep == NULL)\r
++              return -ENOMEM;\r
++      return 0;\r
++}\r
++\r
++\r
++static void destroy_inodecache(void)\r
++{\r
++      kmem_cache_destroy(squashfs_inode_cachep);\r
++}\r
++\r
++\r
++module_init(init_squashfs_fs);\r
++module_exit(exit_squashfs_fs);\r
++MODULE_DESCRIPTION("squashfs 3.2-r2, a compressed read-only filesystem, and LZMA suppport for slax.org");\r
++MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>, and LZMA suppport for slax.org by jro");\r
++MODULE_LICENSE("GPL");\r
+diff -urN linux-2.6.23/fs/squashfs/module.c linux-2.6.23.sqlzma/fs/squashfs/module.c\r
+--- linux-2.6.23/fs/squashfs/module.c  1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/module.c   2007-10-14 12:58:25.000000000 -0400\r
+@@ -0,0 +1,36 @@\r
++\r
++/*\r
++ * Copyright (C) 2006 Junjiro Okajima\r
++ * Copyright (C) 2006 Tomas Matejicek, slax.org\r
++ *\r
++ * LICENSE follows the described one in lzma.txt.\r
++ */\r
++\r
++/* $Id: module.c,v 1.5 2006/11/27 03:54:58 jro Exp $ */\r
++\r
++#include <linux/init.h>\r
++#include <linux/module.h>\r
++\r
++#include "LzmaDecode.c"\r
++\r
++EXPORT_SYMBOL(LzmaDecodeProperties);\r
++EXPORT_SYMBOL(LzmaDecode);\r
++\r
++#if 0\r
++static int __init unlzma_init(void)\r
++{\r
++      return 0;\r
++}\r
++\r
++static void __exit unlzma_exit(void)\r
++{\r
++}\r
++\r
++module_init(unlzma_init);\r
++module_exit(unlzma_exit);\r
++#endif\r
++\r
++MODULE_LICENSE("GPL");\r
++MODULE_VERSION("$Id: module.c,v 1.5 2006/11/27 03:54:58 jro Exp $");\r
++MODULE_DESCRIPTION("LZMA uncompress. "\r
++                 "A tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org.");\r
+diff -urN linux-2.6.23/fs/squashfs/sqlzma.h linux-2.6.23.sqlzma/fs/squashfs/sqlzma.h\r
+--- linux-2.6.23/fs/squashfs/sqlzma.h  1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/sqlzma.h   2007-10-14 13:07:12.000000000 -0400\r
+@@ -0,0 +1,79 @@\r
++/*\r
++ * Copyright (C) 2006 Junjiro Okajima\r
++ * Copyright (C) 2006 Tomas Matejicek, slax.org\r
++ *\r
++ * LICENSE follows the described one in lzma.\r
++ */\r
++\r
++/* $Id: sqlzma.h,v 1.13 2007/01/07 15:12:48 jro Exp $ */\r
++\r
++#ifndef __sqlzma_h__\r
++#define __sqlzma_h__\r
++\r
++#ifndef __KERNEL__\r
++#include <stdlib.h>\r
++#include <string.h>\r
++#include <zlib.h>\r
++#ifdef _REENTRANT\r
++#include <pthread.h>\r
++#endif\r
++#else\r
++#include <linux/zlib.h>\r
++#endif\r
++#define _7ZIP_BYTE_DEFINED\r
++\r
++/*\r
++ * detect the compression method automatically by the first byte of compressed\r
++ * data.\r
++ * according to rfc1950, the first byte of zlib compression must be 0x?8.\r
++ */\r
++#define is_lzma(c)    (c == 0x5d)\r
++\r
++/* ---------------------------------------------------------------------- */\r
++\r
++#ifdef __cplusplus\r
++extern "C" {\r
++#endif\r
++\r
++#ifndef __KERNEL__\r
++/* for mksquashfs only */\r
++int sqlzma_cm(int lzma, z_stream *stream, Bytef *next_in, uInt avail_in,\r
++            Bytef *next_out, uInt avail_out);\r
++#endif\r
++\r
++/* ---------------------------------------------------------------------- */\r
++/*\r
++ * Three patterns for sqlzma uncompression. very dirty code.\r
++ * - kernel space (squashfs kernel module)\r
++ * - user space with pthread (mksquashfs)\r
++ * - user space without pthread (unsquashfs)\r
++ */\r
++\r
++struct sized_buf {\r
++      unsigned int    sz;\r
++      unsigned char   *buf;\r
++};\r
++\r
++enum {SQUN_PROB, SQUN_RESULT, SQUN_LAST};\r
++struct sqlzma_un {\r
++      int                     un_lzma;\r
++      struct sized_buf        un_a[SQUN_LAST];\r
++      unsigned char           un_prob[31960]; /* unlzma 64KB */\r
++      z_stream                un_stream;\r
++#define un_cmbuf      un_stream.next_in\r
++#define un_cmlen      un_stream.avail_in\r
++#define un_resbuf     un_stream.next_out\r
++#define un_resroom    un_stream.avail_out\r
++#define un_reslen     un_stream.total_out\r
++};\r
++\r
++int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz);\r
++int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst);\r
++void sqlzma_fin(struct sqlzma_un *un);\r
++\r
++/* ---------------------------------------------------------------------- */\r
++\r
++#ifdef __cplusplus\r
++};\r
++#endif\r
++#endif\r
+diff -urN linux-2.6.23/fs/squashfs/sqmagic.h linux-2.6.23.sqlzma/fs/squashfs/sqmagic.h\r
+--- linux-2.6.23/fs/squashfs/sqmagic.h 1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/sqmagic.h  2007-10-14 14:32:24.000000000 -0400\r
+@@ -0,0 +1,17 @@\r
++/*\r
++ * Copyright (C) 2006 Junjiro Okajima\r
++ * Copyright (C) 2006 Tomas Matejicek, slax.org\r
++ *\r
++ * LICENSE must follow the one in squashfs.\r
++ */\r
++\r
++/* $Id: sqmagic.h,v 1.2 2006/11/27 03:54:58 jro Exp $ */\r
++\r
++#ifndef __sqmagic_h__\r
++#define __sqmagic_h__\r
++\r
++/* see SQUASHFS_MAGIC in squashfs_fs.h */\r
++#define SQUASHFS_MAGIC_LZMA           0x71736873\r
++#define SQUASHFS_MAGIC_LZMA_SWAP      0x73687371\r
++\r
++#endif\r
+diff -urN linux-2.6.23/fs/squashfs/squashfs.h linux-2.6.23.sqlzma/fs/squashfs/squashfs.h\r
+--- linux-2.6.23/fs/squashfs/squashfs.h        1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/squashfs.h 2007-10-14 10:24:31.000000000 -0400\r
+@@ -0,0 +1,87 @@\r
++/*\r
++ * Squashfs - a compressed read only filesystem for Linux\r
++ *\r
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
++ * Phillip Lougher <phillip@lougher.org.uk>\r
++ *\r
++ * This program is free software; you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License\r
++ * as published by the Free Software Foundation; either version 2,\r
++ * or (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program; if not, write to the Free Software\r
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
++ *\r
++ * squashfs.h\r
++ */\r
++\r
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY\r
++#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY\r
++#endif\r
++\r
++#ifdef SQUASHFS_TRACE\r
++#define TRACE(s, args...)     printk(KERN_NOTICE "SQUASHFS: "s, ## args)\r
++#else\r
++#define TRACE(s, args...)     {}\r
++#endif\r
++\r
++#define ERROR(s, args...)     printk(KERN_ERR "SQUASHFS error: "s, ## args)\r
++\r
++#define SERROR(s, args...)    do { \\r
++                              if (!silent) \\r
++                              printk(KERN_ERR "SQUASHFS error: "s, ## args);\\r
++                              } while(0)\r
++\r
++#define WARNING(s, args...)   printk(KERN_WARNING "SQUASHFS: "s, ## args)\r
++\r
++static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)\r
++{\r
++      return list_entry(inode, struct squashfs_inode_info, vfs_inode);\r
++}\r
++\r
++#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)\r
++#define SQSH_EXTERN\r
++extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,\r
++                              long long index, unsigned int length,\r
++                              long long *next_index, int srclength);\r
++extern int squashfs_get_cached_block(struct super_block *s, char *buffer,\r
++                              long long block, unsigned int offset,\r
++                              int length, long long *next_block,\r
++                              unsigned int *next_offset);\r
++extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct\r
++                                      squashfs_fragment_cache *fragment);\r
++extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block\r
++                                      *s, long long start_block,\r
++                                      int length);\r
++extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number);\r
++extern const struct address_space_operations squashfs_symlink_aops;\r
++extern const struct address_space_operations squashfs_aops;\r
++extern const struct address_space_operations squashfs_aops_4K;\r
++extern struct inode_operations squashfs_dir_inode_ops;\r
++#else\r
++#define SQSH_EXTERN static\r
++#endif\r
++\r
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY\r
++extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);\r
++#else\r
++static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)\r
++{\r
++      return 0;\r
++}\r
++#endif\r
++\r
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY\r
++extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);\r
++#else\r
++static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)\r
++{\r
++      return 0;\r
++}\r
++#endif\r
+diff -urN linux-2.6.23/fs/squashfs/squashfs2_0.c linux-2.6.23.sqlzma/fs/squashfs/squashfs2_0.c\r
+--- linux-2.6.23/fs/squashfs/squashfs2_0.c     1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/squashfs2_0.c      2007-10-14 10:24:31.000000000 -0400\r
+@@ -0,0 +1,742 @@\r
++/*\r
++ * Squashfs - a compressed read only filesystem for Linux\r
++ *\r
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
++ * Phillip Lougher <phillip@lougher.org.uk>\r
++ *\r
++ * This program is free software; you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License\r
++ * as published by the Free Software Foundation; either version 2,\r
++ * or (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program; if not, write to the Free Software\r
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
++ *\r
++ * squashfs2_0.c\r
++ */\r
++\r
++#include <linux/squashfs_fs.h>\r
++#include <linux/module.h>\r
++#include <linux/zlib.h>\r
++#include <linux/fs.h>\r
++#include <linux/squashfs_fs_sb.h>\r
++#include <linux/squashfs_fs_i.h>\r
++\r
++#include "squashfs.h"\r
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);\r
++static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,\r
++                              struct nameidata *);\r
++\r
++static struct file_operations squashfs_dir_ops_2 = {\r
++      .read = generic_read_dir,\r
++      .readdir = squashfs_readdir_2\r
++};\r
++\r
++static struct inode_operations squashfs_dir_inode_ops_2 = {\r
++      .lookup = squashfs_lookup_2\r
++};\r
++\r
++static unsigned char squashfs_filetype_table[] = {\r
++      DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK\r
++};\r
++\r
++static int read_fragment_index_table_2(struct super_block *s)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++\r
++      if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2\r
++                                      (sblk->fragments), GFP_KERNEL))) {\r
++              ERROR("Failed to allocate uid/gid table\n");\r
++              return 0;\r
++      }\r
++   \r
++      if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&\r
++                                      !squashfs_read_data(s, (char *)\r
++                                      msblk->fragment_index_2,\r
++                                      sblk->fragment_table_start,\r
++                                      SQUASHFS_FRAGMENT_INDEX_BYTES_2\r
++                                      (sblk->fragments) |\r
++                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {\r
++              ERROR("unable to read fragment index table\n");\r
++              return 0;\r
++      }\r
++\r
++      if (msblk->swap) {\r
++              int i;\r
++              unsigned int fragment;\r
++\r
++              for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);\r
++                                                                      i++) {\r
++                      SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),\r
++                                              &msblk->fragment_index_2[i], 1);\r
++                      msblk->fragment_index_2[i] = fragment;\r
++              }\r
++      }\r
++\r
++      return 1;\r
++}\r
++\r
++\r
++static int get_fragment_location_2(struct super_block *s, unsigned int fragment,\r
++                              long long *fragment_start_block,\r
++                              unsigned int *fragment_size)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      long long start_block =\r
++              msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];\r
++      int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);\r
++      struct squashfs_fragment_entry_2 fragment_entry;\r
++\r
++      if (msblk->swap) {\r
++              struct squashfs_fragment_entry_2 sfragment_entry;\r
++\r
++              if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,\r
++                                      start_block, offset,\r
++                                      sizeof(sfragment_entry), &start_block,\r
++                                      &offset))\r
++                      goto out;\r
++              SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);\r
++      } else\r
++              if (!squashfs_get_cached_block(s, (char *) &fragment_entry,\r
++                                      start_block, offset,\r
++                                      sizeof(fragment_entry), &start_block,\r
++                                      &offset))\r
++                      goto out;\r
++\r
++      *fragment_start_block = fragment_entry.start_block;\r
++      *fragment_size = fragment_entry.size;\r
++\r
++      return 1;\r
++\r
++out:\r
++      return 0;\r
++}\r
++\r
++\r
++static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,\r
++              struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)\r
++{\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++\r
++      i->i_ino = ino;\r
++      i->i_mtime.tv_sec = sblk->mkfs_time;\r
++      i->i_atime.tv_sec = sblk->mkfs_time;\r
++      i->i_ctime.tv_sec = sblk->mkfs_time;\r
++      i->i_uid = msblk->uid[inodeb->uid];\r
++      i->i_mode = inodeb->mode;\r
++      i->i_nlink = 1;\r
++      i->i_size = 0;\r
++      if (inodeb->guid == SQUASHFS_GUIDS)\r
++              i->i_gid = i->i_uid;\r
++      else\r
++              i->i_gid = msblk->guid[inodeb->guid];\r
++}\r
++\r
++\r
++static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode)\r
++{\r
++      struct super_block *s = i->i_sb;\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      unsigned int block = SQUASHFS_INODE_BLK(inode) +\r
++              sblk->inode_table_start;\r
++      unsigned int offset = SQUASHFS_INODE_OFFSET(inode);\r
++      unsigned int ino = i->i_ino;\r
++      long long next_block;\r
++      unsigned int next_offset;\r
++      union squashfs_inode_header_2 id, sid;\r
++      struct squashfs_base_inode_header_2 *inodeb = &id.base,\r
++                                        *sinodeb = &sid.base;\r
++\r
++      TRACE("Entered squashfs_iget\n");\r
++\r
++      if (msblk->swap) {\r
++              if (!squashfs_get_cached_block(s, (char *) sinodeb, block,\r
++                                      offset, sizeof(*sinodeb), &next_block,\r
++                                      &next_offset))\r
++                      goto failed_read;\r
++              SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,\r
++                                      sizeof(*sinodeb));\r
++      } else\r
++              if (!squashfs_get_cached_block(s, (char *) inodeb, block,\r
++                                      offset, sizeof(*inodeb), &next_block,\r
++                                      &next_offset))\r
++                      goto failed_read;\r
++\r
++      squashfs_new_inode(msblk, i, inodeb, ino);\r
++\r
++      switch(inodeb->inode_type) {\r
++              case SQUASHFS_FILE_TYPE: {\r
++                      struct squashfs_reg_inode_header_2 *inodep = &id.reg;\r
++                      struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;\r
++                      long long frag_blk;\r
++                      unsigned int frag_size = 0;\r
++                              \r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      frag_blk = SQUASHFS_INVALID_BLK;\r
++                      if (inodep->fragment != SQUASHFS_INVALID_FRAG &&\r
++                                      !get_fragment_location_2(s,\r
++                                      inodep->fragment, &frag_blk, &frag_size))\r
++                              goto failed_read;\r
++                              \r
++                      i->i_size = inodep->file_size;\r
++                      i->i_fop = &generic_ro_fops;\r
++                      i->i_mode |= S_IFREG;\r
++                      i->i_mtime.tv_sec = inodep->mtime;\r
++                      i->i_atime.tv_sec = inodep->mtime;\r
++                      i->i_ctime.tv_sec = inodep->mtime;\r
++                      i->i_blocks = ((i->i_size - 1) >> 9) + 1;\r
++                      SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;\r
++                      SQUASHFS_I(i)->u.s1.fragment_size = frag_size;\r
++                      SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->u.s1.block_list_start = next_block;\r
++                      SQUASHFS_I(i)->offset = next_offset;\r
++                      if (sblk->block_size > 4096)\r
++                              i->i_data.a_ops = &squashfs_aops;\r
++                      else\r
++                              i->i_data.a_ops = &squashfs_aops_4K;\r
++\r
++                      TRACE("File inode %x:%x, start_block %x, "\r
++                                      "block_list_start %llx, offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->start_block, next_block,\r
++                                      next_offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_DIR_TYPE: {\r
++                      struct squashfs_dir_inode_header_2 *inodep = &id.dir;\r
++                      struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_size = inodep->file_size;\r
++                      i->i_op = &squashfs_dir_inode_ops_2;\r
++                      i->i_fop = &squashfs_dir_ops_2;\r
++                      i->i_mode |= S_IFDIR;\r
++                      i->i_mtime.tv_sec = inodep->mtime;\r
++                      i->i_atime.tv_sec = inodep->mtime;\r
++                      i->i_ctime.tv_sec = inodep->mtime;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->offset = inodep->offset;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_count = 0;\r
++                      SQUASHFS_I(i)->u.s2.parent_inode = 0;\r
++\r
++                      TRACE("Directory inode %x:%x, start_block %x, offset "\r
++                                      "%x\n", SQUASHFS_INODE_BLK(inode),\r
++                                      offset, inodep->start_block,\r
++                                      inodep->offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_LDIR_TYPE: {\r
++                      struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;\r
++                      struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,\r
++                                              sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_size = inodep->file_size;\r
++                      i->i_op = &squashfs_dir_inode_ops_2;\r
++                      i->i_fop = &squashfs_dir_ops_2;\r
++                      i->i_mode |= S_IFDIR;\r
++                      i->i_mtime.tv_sec = inodep->mtime;\r
++                      i->i_atime.tv_sec = inodep->mtime;\r
++                      i->i_ctime.tv_sec = inodep->mtime;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->offset = inodep->offset;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_start = next_block;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_offset =\r
++                                                              next_offset;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_count =\r
++                                                              inodep->i_count;\r
++                      SQUASHFS_I(i)->u.s2.parent_inode = 0;\r
++\r
++                      TRACE("Long directory inode %x:%x, start_block %x, "\r
++                                      "offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->start_block, inodep->offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_SYMLINK_TYPE: {\r
++                      struct squashfs_symlink_inode_header_2 *inodep =\r
++                                                              &id.symlink;\r
++                      struct squashfs_symlink_inode_header_2 *sinodep =\r
++                                                              &sid.symlink;\r
++      \r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,\r
++                                                              sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_size = inodep->symlink_size;\r
++                      i->i_op = &page_symlink_inode_operations;\r
++                      i->i_data.a_ops = &squashfs_symlink_aops;\r
++                      i->i_mode |= S_IFLNK;\r
++                      SQUASHFS_I(i)->start_block = next_block;\r
++                      SQUASHFS_I(i)->offset = next_offset;\r
++\r
++                      TRACE("Symbolic link inode %x:%x, start_block %llx, "\r
++                                      "offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      next_block, next_offset);\r
++                      break;\r
++               }\r
++               case SQUASHFS_BLKDEV_TYPE:\r
++               case SQUASHFS_CHRDEV_TYPE: {\r
++                      struct squashfs_dev_inode_header_2 *inodep = &id.dev;\r
++                      struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);\r
++                      } else  \r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_mode |= (inodeb->inode_type ==\r
++                                      SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :\r
++                                      S_IFBLK;\r
++                      init_special_inode(i, i->i_mode,\r
++                                      old_decode_dev(inodep->rdev));\r
++\r
++                      TRACE("Device inode %x:%x, rdev %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->rdev);\r
++                      break;\r
++               }\r
++               case SQUASHFS_FIFO_TYPE:\r
++               case SQUASHFS_SOCKET_TYPE: {\r
++\r
++                      i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)\r
++                                                      ? S_IFIFO : S_IFSOCK;\r
++                      init_special_inode(i, i->i_mode, 0);\r
++                      break;\r
++               }\r
++               default:\r
++                      ERROR("Unknown inode type %d in squashfs_iget!\n",\r
++                                      inodeb->inode_type);\r
++                      goto failed_read1;\r
++      }\r
++      \r
++      return 1;\r
++\r
++failed_read:\r
++      ERROR("Unable to read inode [%x:%x]\n", block, offset);\r
++\r
++failed_read1:\r
++      return 0;\r
++}\r
++\r
++\r
++static int get_dir_index_using_offset(struct super_block *s, long long \r
++                              *next_block, unsigned int *next_offset,\r
++                              long long index_start,\r
++                              unsigned int index_offset, int i_count,\r
++                              long long f_pos)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      int i, length = 0;\r
++      struct squashfs_dir_index_2 index;\r
++\r
++      TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",\r
++                                      i_count, (unsigned int) f_pos);\r
++\r
++      if (f_pos == 0)\r
++              goto finish;\r
++\r
++      for (i = 0; i < i_count; i++) {\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_index_2 sindex;\r
++                      squashfs_get_cached_block(s, (char *) &sindex,\r
++                                      index_start, index_offset,\r
++                                      sizeof(sindex), &index_start,\r
++                                      &index_offset);\r
++                      SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);\r
++              } else\r
++                      squashfs_get_cached_block(s, (char *) &index,\r
++                                      index_start, index_offset,\r
++                                      sizeof(index), &index_start,\r
++                                      &index_offset);\r
++\r
++              if (index.index > f_pos)\r
++                      break;\r
++\r
++              squashfs_get_cached_block(s, NULL, index_start, index_offset,\r
++                                      index.size + 1, &index_start,\r
++                                      &index_offset);\r
++\r
++              length = index.index;\r
++              *next_block = index.start_block + sblk->directory_table_start;\r
++      }\r
++\r
++      *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;\r
++\r
++finish:\r
++      return length;\r
++}\r
++\r
++\r
++static int get_dir_index_using_name(struct super_block *s, long long\r
++                              *next_block, unsigned int *next_offset,\r
++                              long long index_start,\r
++                              unsigned int index_offset, int i_count,\r
++                              const char *name, int size)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      int i, length = 0;\r
++      struct squashfs_dir_index_2 *index;\r
++      char *str;\r
++\r
++      TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);\r
++\r
++      if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +\r
++              (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate squashfs_dir_index\n");\r
++              goto failure;\r
++      }\r
++\r
++      index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1);\r
++      strncpy(str, name, size);\r
++      str[size] = '\0';\r
++\r
++      for (i = 0; i < i_count; i++) {\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_index_2 sindex;\r
++                      squashfs_get_cached_block(s, (char *) &sindex,\r
++                                      index_start, index_offset,\r
++                                      sizeof(sindex), &index_start,\r
++                                      &index_offset);\r
++                      SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);\r
++              } else\r
++                      squashfs_get_cached_block(s, (char *) index,\r
++                                      index_start, index_offset,\r
++                                      sizeof(struct squashfs_dir_index_2),\r
++                                      &index_start, &index_offset);\r
++\r
++              squashfs_get_cached_block(s, index->name, index_start,\r
++                                      index_offset, index->size + 1,\r
++                                      &index_start, &index_offset);\r
++\r
++              index->name[index->size + 1] = '\0';\r
++\r
++              if (strcmp(index->name, str) > 0)\r
++                      break;\r
++\r
++              length = index->index;\r
++              *next_block = index->start_block + sblk->directory_table_start;\r
++      }\r
++\r
++      *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;\r
++      kfree(str);\r
++failure:\r
++      return length;\r
++}\r
++\r
++              \r
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)\r
++{\r
++      struct inode *i = file->f_dentry->d_inode;\r
++      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      long long next_block = SQUASHFS_I(i)->start_block +\r
++              sblk->directory_table_start;\r
++      int next_offset = SQUASHFS_I(i)->offset, length = 0,\r
++              dir_count;\r
++      struct squashfs_dir_header_2 dirh;\r
++      struct squashfs_dir_entry_2 *dire;\r
++\r
++      TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);\r
++\r
++      if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +\r
++              SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate squashfs_dir_entry\n");\r
++              goto finish;\r
++      }\r
++\r
++      length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_start,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_count,\r
++                              file->f_pos);\r
++\r
++      while (length < i_size_read(i)) {\r
++              /* read directory header */\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_header_2 sdirh;\r
++                      \r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,\r
++                                      next_block, next_offset, sizeof(sdirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(sdirh);\r
++                      SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);\r
++              } else {\r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,\r
++                                      next_block, next_offset, sizeof(dirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(dirh);\r
++              }\r
++\r
++              dir_count = dirh.count + 1;\r
++              while (dir_count--) {\r
++                      if (msblk->swap) {\r
++                              struct squashfs_dir_entry_2 sdire;\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              &sdire, next_block, next_offset,\r
++                                              sizeof(sdire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              \r
++                              length += sizeof(sdire);\r
++                              SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);\r
++                      } else {\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              dire, next_block, next_offset,\r
++                                              sizeof(*dire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                              length += sizeof(*dire);\r
++                      }\r
++\r
++                      if (!squashfs_get_cached_block(i->i_sb, dire->name,\r
++                                              next_block, next_offset,\r
++                                              dire->size + 1, &next_block,\r
++                                              &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += dire->size + 1;\r
++\r
++                      if (file->f_pos >= length)\r
++                              continue;\r
++\r
++                      dire->name[dire->size + 1] = '\0';\r
++\r
++                      TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",\r
++                                      (unsigned int) dirent, dire->name,\r
++                                      dire->size + 1, (int) file->f_pos,\r
++                                      dirh.start_block, dire->offset,\r
++                                      squashfs_filetype_table[dire->type]);\r
++\r
++                      if (filldir(dirent, dire->name, dire->size + 1,\r
++                                      file->f_pos, SQUASHFS_MK_VFS_INODE(\r
++                                      dirh.start_block, dire->offset),\r
++                                      squashfs_filetype_table[dire->type])\r
++                                      < 0) {\r
++                              TRACE("Filldir returned less than 0\n");\r
++                              goto finish;\r
++                      }\r
++                      file->f_pos = length;\r
++              }\r
++      }\r
++\r
++finish:\r
++      kfree(dire);\r
++      return 0;\r
++\r
++failed_read:\r
++      ERROR("Unable to read directory block [%llx:%x]\n", next_block,\r
++              next_offset);\r
++      kfree(dire);\r
++      return 0;\r
++}\r
++\r
++\r
++static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,\r
++                              struct nameidata *nd)\r
++{\r
++      const unsigned char *name = dentry->d_name.name;\r
++      int len = dentry->d_name.len;\r
++      struct inode *inode = NULL;\r
++      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      long long next_block = SQUASHFS_I(i)->start_block +\r
++                              sblk->directory_table_start;\r
++      int next_offset = SQUASHFS_I(i)->offset, length = 0,\r
++                              dir_count;\r
++      struct squashfs_dir_header_2 dirh;\r
++      struct squashfs_dir_entry_2 *dire;\r
++      int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;\r
++\r
++      TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset);\r
++\r
++      if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +\r
++              SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate squashfs_dir_entry\n");\r
++              goto exit_loop;\r
++      }\r
++\r
++      if (len > SQUASHFS_NAME_LEN)\r
++              goto exit_loop;\r
++\r
++      length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_start,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_count, name,\r
++                              len);\r
++\r
++      while (length < i_size_read(i)) {\r
++              /* read directory header */\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_header_2 sdirh;\r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,\r
++                                      next_block, next_offset, sizeof(sdirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(sdirh);\r
++                      SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);\r
++              } else {\r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,\r
++                                      next_block, next_offset, sizeof(dirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(dirh);\r
++              }\r
++\r
++              dir_count = dirh.count + 1;\r
++              while (dir_count--) {\r
++                      if (msblk->swap) {\r
++                              struct squashfs_dir_entry_2 sdire;\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              &sdire, next_block,next_offset,\r
++                                              sizeof(sdire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              \r
++                              length += sizeof(sdire);\r
++                              SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);\r
++                      } else {\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              dire, next_block,next_offset,\r
++                                              sizeof(*dire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                              length += sizeof(*dire);\r
++                      }\r
++\r
++                      if (!squashfs_get_cached_block(i->i_sb, dire->name,\r
++                                      next_block, next_offset, dire->size + 1,\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += dire->size + 1;\r
++\r
++                      if (sorted && name[0] < dire->name[0])\r
++                              goto exit_loop;\r
++\r
++                      if ((len == dire->size + 1) && !strncmp(name,\r
++                                              dire->name, len)) {\r
++                              squashfs_inode_t ino =\r
++                                      SQUASHFS_MKINODE(dirh.start_block,\r
++                                      dire->offset);\r
++                              unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block,\r
++                                      dire->offset);\r
++\r
++                              TRACE("calling squashfs_iget for directory "\r
++                                      "entry %s, inode %x:%x, %lld\n", name,\r
++                                      dirh.start_block, dire->offset, ino);\r
++\r
++                              inode = squashfs_iget(i->i_sb, ino, inode_number);\r
++\r
++                              goto exit_loop;\r
++                      }\r
++              }\r
++      }\r
++\r
++exit_loop:\r
++      kfree(dire);\r
++      d_add(dentry, inode);\r
++      return ERR_PTR(0);\r
++\r
++failed_read:\r
++      ERROR("Unable to read directory block [%llx:%x]\n", next_block,\r
++              next_offset);\r
++      goto exit_loop;\r
++}\r
++\r
++\r
++int squashfs_2_0_supported(struct squashfs_sb_info *msblk)\r
++{\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++\r
++      msblk->read_inode = squashfs_read_inode_2;\r
++      msblk->read_fragment_index_table = read_fragment_index_table_2;\r
++\r
++      sblk->bytes_used = sblk->bytes_used_2;\r
++      sblk->uid_start = sblk->uid_start_2;\r
++      sblk->guid_start = sblk->guid_start_2;\r
++      sblk->inode_table_start = sblk->inode_table_start_2;\r
++      sblk->directory_table_start = sblk->directory_table_start_2;\r
++      sblk->fragment_table_start = sblk->fragment_table_start_2;\r
++\r
++      return 1;\r
++}\r
+diff -urN linux-2.6.23/fs/squashfs/uncomp.c linux-2.6.23.sqlzma/fs/squashfs/uncomp.c\r
+--- linux-2.6.23/fs/squashfs/uncomp.c  1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/uncomp.c   2007-10-14 12:43:55.000000000 -0400\r
+@@ -0,0 +1,221 @@\r
++/*\r
++ * Copyright (C) 2006, 2007 Junjiro Okajima\r
++ * Copyright (C) 2006, 2007 Tomas Matejicek, slax.org\r
++ *\r
++ * LICENSE follows the described one in lzma.txt.\r
++ */\r
++\r
++/* $Id: uncomp.c,v 1.30 2007/03/04 12:45:53 jro Exp $ */\r
++\r
++/* extract some parts from lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c */\r
++\r
++#ifndef __KERNEL__\r
++#include <stdio.h>\r
++#include <stdlib.h>\r
++#include <string.h>\r
++#include <errno.h>\r
++#include <assert.h>\r
++#include <pthread.h>\r
++#define unlikely(x)           __builtin_expect(!!(x), 0)\r
++#define BUG_ON(x)             assert(!(x))\r
++/* sqlzma buffers are always larger than a page. true? */\r
++#define kmalloc(sz,gfp)               malloc(sz)\r
++#define kfree(p)              free(p)\r
++#define zlib_inflate(s, f)    inflate(s, f)\r
++#define zlib_inflateInit(s)   inflateInit(s)\r
++#define zlib_inflateReset(s)  inflateReset(s)\r
++#define zlib_inflateEnd(s)    inflateEnd(s)\r
++#else\r
++#include <linux/init.h>\r
++#include <linux/module.h>\r
++#include <linux/kernel.h>\r
++#include <linux/vmalloc.h>\r
++#ifndef WARN_ON_ONCE\r
++#define WARN_ON_ONCE(b)       WARN_ON(b)\r
++#endif\r
++#endif /* __KERNEL__ */\r
++\r
++#include "sqlzma.h"\r
++#include "LzmaDecode.h"\r
++\r
++static int LzmaUncompress(struct sqlzma_un *un)\r
++{\r
++      int err, i, ret;\r
++      SizeT outSize, inProcessed, outProcessed, srclen;\r
++      /* it's about 24-80 bytes structure, if int is 32-bit */\r
++      CLzmaDecoderState state;\r
++      unsigned char *dst, *src, a[8];\r
++      struct sized_buf *sbuf;\r
++\r
++      /* Decode LZMA properties and allocate memory */\r
++      err = -EINVAL;\r
++      src = (unsigned char *)un->un_cmbuf;\r
++      ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE);\r
++      src += LZMA_PROPERTIES_SIZE;\r
++      if (unlikely(ret != LZMA_RESULT_OK))\r
++              goto out;\r
++      i = LzmaGetNumProbs(&state.Properties);\r
++      if (unlikely(i <= 0))\r
++              i = 1;\r
++      i *= sizeof(CProb);\r
++      sbuf = un->un_a + SQUN_PROB;\r
++      if (unlikely(sbuf->sz < i)) {\r
++              if (sbuf->buf && sbuf->buf != un->un_prob)\r
++                      kfree(sbuf->buf);\r
++#ifdef __KERNEL__\r
++              printk("%s:%d: %d --> %d\n", __func__, __LINE__, sbuf->sz, i);\r
++#else\r
++              printf("%d --> %d\n", sbuf->sz, i);\r
++#endif\r
++              err = -ENOMEM;\r
++              sbuf->sz = 0;\r
++              sbuf->buf = kmalloc(i, GFP_ATOMIC);\r
++              if (unlikely(!sbuf->buf))\r
++                      goto out;\r
++              sbuf->sz = i;\r
++      }\r
++      state.Probs = (void*)sbuf->buf;\r
++\r
++      /* Read uncompressed size */\r
++      memcpy(a, src, sizeof(a));\r
++      src += sizeof(a);\r
++      outSize = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24);\r
++\r
++      err = -EINVAL;\r
++      dst = un->un_resbuf;\r
++      if (unlikely(!dst || outSize > un->un_reslen))\r
++              goto out;\r
++      un->un_reslen = outSize;\r
++      srclen = un->un_cmlen - (src - un->un_cmbuf);\r
++\r
++      /* Decompress */\r
++      err = LzmaDecode(&state, src, srclen, &inProcessed, dst, outSize,\r
++                       &outProcessed);\r
++      if (err)\r
++              err = -EINVAL;\r
++\r
++ out:\r
++#ifndef __KERNEL__\r
++      if (err)\r
++              fprintf(stderr, "err %d\n", err);\r
++#endif\r
++      return err;\r
++}\r
++\r
++int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src,\r
++            struct sized_buf *dst)\r
++{\r
++      int err, by_lzma = 0;\r
++      if (un->un_lzma && is_lzma(*src->buf)) {\r
++              by_lzma = 1;\r
++              un->un_cmbuf = src->buf;\r
++              un->un_cmlen = src->sz;\r
++              un->un_resbuf = dst->buf;\r
++              un->un_reslen = dst->sz;\r
++\r
++              /* this library is thread-safe */\r
++              err = LzmaUncompress(un);\r
++              goto out;\r
++      }\r
++\r
++      err = zlib_inflateReset(&un->un_stream);\r
++      if (unlikely(err != Z_OK))\r
++              goto out;\r
++      un->un_stream.next_in = src->buf;\r
++      un->un_stream.avail_in = src->sz;\r
++      un->un_stream.next_out = dst->buf;\r
++      un->un_stream.avail_out = dst->sz;\r
++      err = zlib_inflate(&un->un_stream, Z_FINISH);\r
++      if (err == Z_STREAM_END)\r
++              err = 0;\r
++\r
++ out:\r
++      if (err) {\r
++#ifdef __KERNEL__\r
++              WARN_ON_ONCE(1);\r
++#else\r
++              char a[64] = "ZLIB ";\r
++              if (by_lzma) {\r
++                      strcpy(a, "LZMA ");\r
++#ifdef _REENTRANT\r
++                      strerror_r(err, a + 5, sizeof(a) - 5);\r
++#else\r
++                      strncat(a, strerror(err), sizeof(a) - 5);\r
++#endif\r
++              } else\r
++                      strncat(a, zError(err), sizeof(a) - 5);\r
++              fprintf(stderr, "%s: %.*s\n", __func__, sizeof(a), a);\r
++#endif\r
++      }\r
++      return err;\r
++}\r
++\r
++int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz)\r
++{\r
++      int err;\r
++\r
++      err = -ENOMEM;\r
++      un->un_lzma = do_lzma;\r
++      memset(un->un_a, 0, sizeof(un->un_a));\r
++      un->un_a[SQUN_PROB].buf = un->un_prob;\r
++      un->un_a[SQUN_PROB].sz = sizeof(un->un_prob);\r
++      if (res_sz) {\r
++              un->un_a[SQUN_RESULT].buf = kmalloc(res_sz, GFP_KERNEL);\r
++              if (unlikely(!un->un_a[SQUN_RESULT].buf))\r
++                      return err;\r
++              un->un_a[SQUN_RESULT].sz = res_sz;\r
++      }\r
++\r
++      un->un_stream.next_in = NULL;\r
++      un->un_stream.avail_in = 0;\r
++#ifdef __KERNEL__\r
++      un->un_stream.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);\r
++      if (unlikely(!un->un_stream.workspace))\r
++              return err;\r
++#else\r
++      un->un_stream.opaque = NULL;\r
++      un->un_stream.zalloc = Z_NULL;\r
++      un->un_stream.zfree = Z_NULL;\r
++#endif\r
++      err = zlib_inflateInit(&un->un_stream);\r
++      if (unlikely(err == Z_MEM_ERROR))\r
++              return -ENOMEM;\r
++      BUG_ON(err);\r
++      return err;\r
++}\r
++\r
++void sqlzma_fin(struct sqlzma_un *un)\r
++{\r
++      int i;\r
++      for (i = 0; i < SQUN_LAST; i++)\r
++              if (un->un_a[i].buf && un->un_a[i].buf != un->un_prob)\r
++                      kfree(un->un_a[i].buf);\r
++      BUG_ON(zlib_inflateEnd(&un->un_stream) != Z_OK);\r
++}\r
++\r
++#ifdef __KERNEL__\r
++EXPORT_SYMBOL(sqlzma_un);\r
++EXPORT_SYMBOL(sqlzma_init);\r
++EXPORT_SYMBOL(sqlzma_fin);\r
++\r
++#if 0\r
++static int __init sqlzma_init(void)\r
++{\r
++      return 0;\r
++}\r
++\r
++static void __exit sqlzma_exit(void)\r
++{\r
++}\r
++\r
++module_init(sqlzma_init);\r
++module_exit(sqlzma_exit);\r
++#endif\r
++\r
++MODULE_LICENSE("GPL");\r
++MODULE_AUTHOR("Junjiro Okajima <hooanon05 at yahoo dot co dot jp>");\r
++MODULE_VERSION("$Id: uncomp.c,v 1.30 2007/03/04 12:45:53 jro Exp $");\r
++MODULE_DESCRIPTION("LZMA uncompress for squashfs. "\r
++                 "Some functions for squashfs to support LZMA and "\r
++                 "a tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org.");\r
++#endif\r
+diff -urN linux-2.6.23/include/linux/squashfs_fs.h linux-2.6.23.sqlzma/include/linux/squashfs_fs.h\r
+--- linux-2.6.23/include/linux/squashfs_fs.h   1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/include/linux/squashfs_fs.h    2007-10-14 10:24:31.000000000 -0400\r
+@@ -0,0 +1,934 @@\r
++#ifndef SQUASHFS_FS\r
++#define SQUASHFS_FS\r
++\r
++/*\r
++ * Squashfs\r
++ *\r
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
++ * Phillip Lougher <phillip@lougher.org.uk>\r
++ *\r
++ * This program is free software; you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License\r
++ * as published by the Free Software Foundation; either version 2,\r
++ * or (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program; if not, write to the Free Software\r
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
++ *\r
++ * squashfs_fs.h\r
++ */\r
++\r
++#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY\r
++#define CONFIG_SQUASHFS_2_0_COMPATIBILITY\r
++#endif\r
++\r
++#ifdef        CONFIG_SQUASHFS_VMALLOC\r
++#define SQUASHFS_ALLOC(a)             vmalloc(a)\r
++#define SQUASHFS_FREE(a)              vfree(a)\r
++#else\r
++#define SQUASHFS_ALLOC(a)             kmalloc(a, GFP_KERNEL)\r
++#define SQUASHFS_FREE(a)              kfree(a)\r
++#endif\r
++#define SQUASHFS_CACHED_FRAGMENTS     CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE     \r
++#define SQUASHFS_MAJOR                        3\r
++#define SQUASHFS_MINOR                        0\r
++#define SQUASHFS_MAGIC                        0x73717368\r
++#define SQUASHFS_MAGIC_SWAP           0x68737173\r
++#define SQUASHFS_START                        0\r
++\r
++/* size of metadata (inode and directory) blocks */\r
++#define SQUASHFS_METADATA_SIZE                8192\r
++#define SQUASHFS_METADATA_LOG         13\r
++\r
++/* default size of data blocks */\r
++#define SQUASHFS_FILE_SIZE            65536\r
++#define SQUASHFS_FILE_LOG             16\r
++\r
++#define SQUASHFS_FILE_MAX_SIZE                65536\r
++\r
++/* Max number of uids and gids */\r
++#define SQUASHFS_UIDS                 256\r
++#define SQUASHFS_GUIDS                        255\r
++\r
++/* Max length of filename (not 255) */\r
++#define SQUASHFS_NAME_LEN             256\r
++\r
++#define SQUASHFS_INVALID              ((long long) 0xffffffffffff)\r
++#define SQUASHFS_INVALID_FRAG         ((unsigned int) 0xffffffff)\r
++#define SQUASHFS_INVALID_BLK          ((long long) -1)\r
++#define SQUASHFS_USED_BLK             ((long long) -2)\r
++\r
++/* Filesystem flags */\r
++#define SQUASHFS_NOI                  0\r
++#define SQUASHFS_NOD                  1\r
++#define SQUASHFS_CHECK                        2\r
++#define SQUASHFS_NOF                  3\r
++#define SQUASHFS_NO_FRAG              4\r
++#define SQUASHFS_ALWAYS_FRAG          5\r
++#define SQUASHFS_DUPLICATE            6\r
++#define SQUASHFS_EXPORT                       7\r
++\r
++#define SQUASHFS_BIT(flag, bit)               ((flag >> bit) & 1)\r
++\r
++#define SQUASHFS_UNCOMPRESSED_INODES(flags)   SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_NOI)\r
++\r
++#define SQUASHFS_UNCOMPRESSED_DATA(flags)     SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_NOD)\r
++\r
++#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags)        SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_NOF)\r
++\r
++#define SQUASHFS_NO_FRAGMENTS(flags)          SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_NO_FRAG)\r
++\r
++#define SQUASHFS_ALWAYS_FRAGMENTS(flags)      SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_ALWAYS_FRAG)\r
++\r
++#define SQUASHFS_DUPLICATES(flags)            SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_DUPLICATE)\r
++\r
++#define SQUASHFS_EXPORTABLE(flags)            SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_EXPORT)\r
++\r
++#define SQUASHFS_CHECK_DATA(flags)            SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_CHECK)\r
++\r
++#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \\r
++              duplicate_checking, exortable)  (noi | (nod << 1) | (check_data << 2) \\r
++              | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \\r
++              (duplicate_checking << 6) | (exportable << 7))\r
++\r
++/* Max number of types and file types */\r
++#define SQUASHFS_DIR_TYPE             1\r
++#define SQUASHFS_FILE_TYPE            2\r
++#define SQUASHFS_SYMLINK_TYPE         3\r
++#define SQUASHFS_BLKDEV_TYPE          4\r
++#define SQUASHFS_CHRDEV_TYPE          5\r
++#define SQUASHFS_FIFO_TYPE            6\r
++#define SQUASHFS_SOCKET_TYPE          7\r
++#define SQUASHFS_LDIR_TYPE            8\r
++#define SQUASHFS_LREG_TYPE            9\r
++\r
++/* 1.0 filesystem type definitions */\r
++#define SQUASHFS_TYPES                        5\r
++#define SQUASHFS_IPC_TYPE             0\r
++\r
++/* Flag whether block is compressed or uncompressed, bit is set if block is\r
++ * uncompressed */\r
++#define SQUASHFS_COMPRESSED_BIT               (1 << 15)\r
++\r
++#define SQUASHFS_COMPRESSED_SIZE(B)   (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \\r
++              (B) & ~SQUASHFS_COMPRESSED_BIT :  SQUASHFS_COMPRESSED_BIT)\r
++\r
++#define SQUASHFS_COMPRESSED(B)                (!((B) & SQUASHFS_COMPRESSED_BIT))\r
++\r
++#define SQUASHFS_COMPRESSED_BIT_BLOCK         (1 << 24)\r
++\r
++#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B)     (((B) & \\r
++      ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \\r
++      ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)\r
++\r
++#define SQUASHFS_COMPRESSED_BLOCK(B)  (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))\r
++\r
++/*\r
++ * Inode number ops.  Inodes consist of a compressed block number, and an\r
++ * uncompressed  offset within that block\r
++ */\r
++#define SQUASHFS_INODE_BLK(a)         ((unsigned int) ((a) >> 16))\r
++\r
++#define SQUASHFS_INODE_OFFSET(a)      ((unsigned int) ((a) & 0xffff))\r
++\r
++#define SQUASHFS_MKINODE(A, B)                ((squashfs_inode_t)(((squashfs_inode_t) (A)\\r
++                                      << 16) + (B)))\r
++\r
++/* Compute 32 bit VFS inode number from squashfs inode number */\r
++#define SQUASHFS_MK_VFS_INODE(a, b)   ((unsigned int) (((a) << 8) + \\r
++                                      ((b) >> 2) + 1))\r
++/* XXX */\r
++\r
++/* Translate between VFS mode and squashfs mode */\r
++#define SQUASHFS_MODE(a)              ((a) & 0xfff)\r
++\r
++/* fragment and fragment table defines */\r
++#define SQUASHFS_FRAGMENT_BYTES(A)    ((A) * sizeof(struct squashfs_fragment_entry))\r
++\r
++#define SQUASHFS_FRAGMENT_INDEX(A)    (SQUASHFS_FRAGMENT_BYTES(A) / \\r
++                                      SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A)     (SQUASHFS_FRAGMENT_BYTES(A) % \\r
++                                              SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_FRAGMENT_INDEXES(A)  ((SQUASHFS_FRAGMENT_BYTES(A) + \\r
++                                      SQUASHFS_METADATA_SIZE - 1) / \\r
++                                      SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_FRAGMENT_INDEX_BYTES(A)      (SQUASHFS_FRAGMENT_INDEXES(A) *\\r
++                                              sizeof(long long))\r
++\r
++/* inode lookup table defines */\r
++#define SQUASHFS_LOOKUP_BYTES(A)      ((A) * sizeof(squashfs_inode_t))\r
++\r
++#define SQUASHFS_LOOKUP_BLOCK(A)              (SQUASHFS_LOOKUP_BYTES(A) / \\r
++                                              SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A)               (SQUASHFS_LOOKUP_BYTES(A) % \\r
++                                              SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_LOOKUP_BLOCKS(A)     ((SQUASHFS_LOOKUP_BYTES(A) + \\r
++                                      SQUASHFS_METADATA_SIZE - 1) / \\r
++                                      SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_LOOKUP_BLOCK_BYTES(A)        (SQUASHFS_LOOKUP_BLOCKS(A) *\\r
++                                      sizeof(long long))\r
++\r
++/* cached data constants for filesystem */\r
++#define SQUASHFS_CACHED_BLKS          8\r
++\r
++#define SQUASHFS_MAX_FILE_SIZE_LOG    64\r
++\r
++#define SQUASHFS_MAX_FILE_SIZE                ((long long) 1 << \\r
++                                      (SQUASHFS_MAX_FILE_SIZE_LOG - 2))\r
++\r
++#define SQUASHFS_MARKER_BYTE          0xff\r
++\r
++/* meta index cache */\r
++#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))\r
++#define SQUASHFS_META_ENTRIES 31\r
++#define SQUASHFS_META_NUMBER  8\r
++#define SQUASHFS_SLOTS                4\r
++\r
++struct meta_entry {\r
++      long long               data_block;\r
++      unsigned int            index_block;\r
++      unsigned short          offset;\r
++      unsigned short          pad;\r
++};\r
++\r
++struct meta_index {\r
++      unsigned int            inode_number;\r
++      unsigned int            offset;\r
++      unsigned short          entries;\r
++      unsigned short          skip;\r
++      unsigned short          locked;\r
++      unsigned short          pad;\r
++      struct meta_entry       meta_entry[SQUASHFS_META_ENTRIES];\r
++};\r
++\r
++\r
++/*\r
++ * definitions for structures on disk\r
++ */\r
++\r
++typedef long long             squashfs_block_t;\r
++typedef long long             squashfs_inode_t;\r
++\r
++struct squashfs_super_block {\r
++      unsigned int            s_magic;\r
++      unsigned int            inodes;\r
++      unsigned int            bytes_used_2;\r
++      unsigned int            uid_start_2;\r
++      unsigned int            guid_start_2;\r
++      unsigned int            inode_table_start_2;\r
++      unsigned int            directory_table_start_2;\r
++      unsigned int            s_major:16;\r
++      unsigned int            s_minor:16;\r
++      unsigned int            block_size_1:16;\r
++      unsigned int            block_log:16;\r
++      unsigned int            flags:8;\r
++      unsigned int            no_uids:8;\r
++      unsigned int            no_guids:8;\r
++      unsigned int            mkfs_time /* time of filesystem creation */;\r
++      squashfs_inode_t        root_inode;\r
++      unsigned int            block_size;\r
++      unsigned int            fragments;\r
++      unsigned int            fragment_table_start_2;\r
++      long long               bytes_used;\r
++      long long               uid_start;\r
++      long long               guid_start;\r
++      long long               inode_table_start;\r
++      long long               directory_table_start;\r
++      long long               fragment_table_start;\r
++      long long               lookup_table_start;\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dir_index {\r
++      unsigned int            index;\r
++      unsigned int            start_block;\r
++      unsigned char           size;\r
++      unsigned char           name[0];\r
++} __attribute__ ((packed));\r
++\r
++#define SQUASHFS_BASE_INODE_HEADER            \\r
++      unsigned int            inode_type:4;   \\r
++      unsigned int            mode:12;        \\r
++      unsigned int            uid:8;          \\r
++      unsigned int            guid:8;         \\r
++      unsigned int            mtime;          \\r
++      unsigned int            inode_number;\r
++\r
++struct squashfs_base_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_ipc_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      unsigned int            nlink;\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dev_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      unsigned int            nlink;\r
++      unsigned short          rdev;\r
++} __attribute__ ((packed));\r
++      \r
++struct squashfs_symlink_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      unsigned int            nlink;\r
++      unsigned short          symlink_size;\r
++      char                    symlink[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_reg_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      squashfs_block_t        start_block;\r
++      unsigned int            fragment;\r
++      unsigned int            offset;\r
++      unsigned int            file_size;\r
++      unsigned short          block_list[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_lreg_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      unsigned int            nlink;\r
++      squashfs_block_t        start_block;\r
++      unsigned int            fragment;\r
++      unsigned int            offset;\r
++      long long               file_size;\r
++      unsigned short          block_list[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dir_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      unsigned int            nlink;\r
++      unsigned int            file_size:19;\r
++      unsigned int            offset:13;\r
++      unsigned int            start_block;\r
++      unsigned int            parent_inode;\r
++} __attribute__  ((packed));\r
++\r
++struct squashfs_ldir_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      unsigned int            nlink;\r
++      unsigned int            file_size:27;\r
++      unsigned int            offset:13;\r
++      unsigned int            start_block;\r
++      unsigned int            i_count:16;\r
++      unsigned int            parent_inode;\r
++      struct squashfs_dir_index       index[0];\r
++} __attribute__  ((packed));\r
++\r
++union squashfs_inode_header {\r
++      struct squashfs_base_inode_header       base;\r
++      struct squashfs_dev_inode_header        dev;\r
++      struct squashfs_symlink_inode_header    symlink;\r
++      struct squashfs_reg_inode_header        reg;\r
++      struct squashfs_lreg_inode_header       lreg;\r
++      struct squashfs_dir_inode_header        dir;\r
++      struct squashfs_ldir_inode_header       ldir;\r
++      struct squashfs_ipc_inode_header        ipc;\r
++};\r
++      \r
++struct squashfs_dir_entry {\r
++      unsigned int            offset:13;\r
++      unsigned int            type:3;\r
++      unsigned int            size:8;\r
++      int                     inode_number:16;\r
++      char                    name[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dir_header {\r
++      unsigned int            count:8;\r
++      unsigned int            start_block;\r
++      unsigned int            inode_number;\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_fragment_entry {\r
++      long long               start_block;\r
++      unsigned int            size;\r
++      unsigned int            pending;\r
++} __attribute__ ((packed));\r
++\r
++extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);\r
++extern int squashfs_uncompress_init(void);\r
++extern int squashfs_uncompress_exit(void);\r
++\r
++/*\r
++ * macros to convert each packed bitfield structure from little endian to big\r
++ * endian and vice versa.  These are needed when creating or using a filesystem\r
++ * on a machine with different byte ordering to the target architecture.\r
++ *\r
++ */\r
++\r
++#define SQUASHFS_SWAP_START \\r
++      int bits;\\r
++      int b_pos;\\r
++      unsigned long long val;\\r
++      unsigned char *s;\\r
++      unsigned char *d;\r
++\r
++#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\\r
++      SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\\r
++      SQUASHFS_SWAP((s)->inodes, d, 32, 32);\\r
++      SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\\r
++      SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\\r
++      SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\\r
++      SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\\r
++      SQUASHFS_SWAP((s)->s_major, d, 224, 16);\\r
++      SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\\r
++      SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\\r
++      SQUASHFS_SWAP((s)->block_log, d, 272, 16);\\r
++      SQUASHFS_SWAP((s)->flags, d, 288, 8);\\r
++      SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\\r
++      SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\\r
++      SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\\r
++      SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\\r
++      SQUASHFS_SWAP((s)->block_size, d, 408, 32);\\r
++      SQUASHFS_SWAP((s)->fragments, d, 440, 32);\\r
++      SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\\r
++      SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\\r
++      SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\\r
++      SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\\r
++      SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\\r
++      SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\\r
++      SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\\r
++      SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\\r
++      SQUASHFS_MEMSET(s, d, n);\\r
++      SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\\r
++      SQUASHFS_SWAP((s)->mode, d, 4, 12);\\r
++      SQUASHFS_SWAP((s)->uid, d, 16, 8);\\r
++      SQUASHFS_SWAP((s)->guid, d, 24, 8);\\r
++      SQUASHFS_SWAP((s)->mtime, d, 32, 32);\\r
++      SQUASHFS_SWAP((s)->inode_number, d, 64, 32);\r
++\r
++#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\\r
++}\r
++\r
++#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_ipc_inode_header))\\r
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_dev_inode_header)); \\r
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->rdev, d, 128, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_symlink_inode_header));\\r
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_reg_inode_header));\\r
++      SQUASHFS_SWAP((s)->start_block, d, 96, 64);\\r
++      SQUASHFS_SWAP((s)->fragment, d, 160, 32);\\r
++      SQUASHFS_SWAP((s)->offset, d, 192, 32);\\r
++      SQUASHFS_SWAP((s)->file_size, d, 224, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_lreg_inode_header));\\r
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 128, 64);\\r
++      SQUASHFS_SWAP((s)->fragment, d, 192, 32);\\r
++      SQUASHFS_SWAP((s)->offset, d, 224, 32);\\r
++      SQUASHFS_SWAP((s)->file_size, d, 256, 64);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_dir_inode_header));\\r
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->file_size, d, 128, 19);\\r
++      SQUASHFS_SWAP((s)->offset, d, 147, 13);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 160, 32);\\r
++      SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_ldir_inode_header));\\r
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->file_size, d, 128, 27);\\r
++      SQUASHFS_SWAP((s)->offset, d, 155, 13);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 168, 32);\\r
++      SQUASHFS_SWAP((s)->i_count, d, 200, 16);\\r
++      SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\\r
++      SQUASHFS_SWAP((s)->index, d, 0, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 32, 32);\\r
++      SQUASHFS_SWAP((s)->size, d, 64, 8);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\\r
++      SQUASHFS_SWAP((s)->count, d, 0, 8);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 8, 32);\\r
++      SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\\r
++      SQUASHFS_SWAP((s)->offset, d, 0, 13);\\r
++      SQUASHFS_SWAP((s)->type, d, 13, 3);\\r
++      SQUASHFS_SWAP((s)->size, d, 16, 8);\\r
++      SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\\r
++      SQUASHFS_SWAP((s)->start_block, d, 0, 64);\\r
++      SQUASHFS_SWAP((s)->size, d, 64, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1)\r
++\r
++#define SQUASHFS_SWAP_SHORTS(s, d, n) {\\r
++      int entry;\\r
++      int bit_position;\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, n * 2);\\r
++      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\r
++                      16)\\r
++              SQUASHFS_SWAP(s[entry], d, bit_position, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_INTS(s, d, n) {\\r
++      int entry;\\r
++      int bit_position;\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, n * 4);\\r
++      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\r
++                      32)\\r
++              SQUASHFS_SWAP(s[entry], d, bit_position, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\\r
++      int entry;\\r
++      int bit_position;\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, n * 8);\\r
++      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\r
++                      64)\\r
++              SQUASHFS_SWAP(s[entry], d, bit_position, 64);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\\r
++      int entry;\\r
++      int bit_position;\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, n * bits / 8);\\r
++      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\r
++                      bits)\\r
++              SQUASHFS_SWAP(s[entry], d, bit_position, bits);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)\r
++#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)\r
++\r
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY\r
++\r
++struct squashfs_base_inode_header_1 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:4; /* index into uid table */\r
++      unsigned int            guid:4; /* index into guid table */\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_ipc_inode_header_1 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:4; /* index into uid table */\r
++      unsigned int            guid:4; /* index into guid table */\r
++      unsigned int            type:4;\r
++      unsigned int            offset:4;\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dev_inode_header_1 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:4; /* index into uid table */\r
++      unsigned int            guid:4; /* index into guid table */\r
++      unsigned short          rdev;\r
++} __attribute__ ((packed));\r
++      \r
++struct squashfs_symlink_inode_header_1 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:4; /* index into uid table */\r
++      unsigned int            guid:4; /* index into guid table */\r
++      unsigned short          symlink_size;\r
++      char                    symlink[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_reg_inode_header_1 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:4; /* index into uid table */\r
++      unsigned int            guid:4; /* index into guid table */\r
++      unsigned int            mtime;\r
++      unsigned int            start_block;\r
++      unsigned int            file_size:32;\r
++      unsigned short          block_list[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dir_inode_header_1 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:4; /* index into uid table */\r
++      unsigned int            guid:4; /* index into guid table */\r
++      unsigned int            file_size:19;\r
++      unsigned int            offset:13;\r
++      unsigned int            mtime;\r
++      unsigned int            start_block:24;\r
++} __attribute__  ((packed));\r
++\r
++#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \\r
++      SQUASHFS_MEMSET(s, d, n);\\r
++      SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\\r
++      SQUASHFS_SWAP((s)->mode, d, 4, 12);\\r
++      SQUASHFS_SWAP((s)->uid, d, 16, 4);\\r
++      SQUASHFS_SWAP((s)->guid, d, 20, 4);\r
++\r
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\\r
++}\r
++\r
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
++                      sizeof(struct squashfs_ipc_inode_header_1));\\r
++      SQUASHFS_SWAP((s)->type, d, 24, 4);\\r
++      SQUASHFS_SWAP((s)->offset, d, 28, 4);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
++                      sizeof(struct squashfs_dev_inode_header_1));\\r
++      SQUASHFS_SWAP((s)->rdev, d, 24, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
++                      sizeof(struct squashfs_symlink_inode_header_1));\\r
++      SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
++                      sizeof(struct squashfs_reg_inode_header_1));\\r
++      SQUASHFS_SWAP((s)->mtime, d, 24, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 56, 32);\\r
++      SQUASHFS_SWAP((s)->file_size, d, 88, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
++                      sizeof(struct squashfs_dir_inode_header_1));\\r
++      SQUASHFS_SWAP((s)->file_size, d, 24, 19);\\r
++      SQUASHFS_SWAP((s)->offset, d, 43, 13);\\r
++      SQUASHFS_SWAP((s)->mtime, d, 56, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 88, 24);\\r
++}\r
++\r
++#endif\r
++\r
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY\r
++\r
++struct squashfs_dir_index_2 {\r
++      unsigned int            index:27;\r
++      unsigned int            start_block:29;\r
++      unsigned char           size;\r
++      unsigned char           name[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_base_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_ipc_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dev_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++      unsigned short          rdev;\r
++} __attribute__ ((packed));\r
++      \r
++struct squashfs_symlink_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++      unsigned short          symlink_size;\r
++      char                    symlink[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_reg_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++      unsigned int            mtime;\r
++      unsigned int            start_block;\r
++      unsigned int            fragment;\r
++      unsigned int            offset;\r
++      unsigned int            file_size:32;\r
++      unsigned short          block_list[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dir_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++      unsigned int            file_size:19;\r
++      unsigned int            offset:13;\r
++      unsigned int            mtime;\r
++      unsigned int            start_block:24;\r
++} __attribute__  ((packed));\r
++\r
++struct squashfs_ldir_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++      unsigned int            file_size:27;\r
++      unsigned int            offset:13;\r
++      unsigned int            mtime;\r
++      unsigned int            start_block:24;\r
++      unsigned int            i_count:16;\r
++      struct squashfs_dir_index_2     index[0];\r
++} __attribute__  ((packed));\r
++\r
++union squashfs_inode_header_2 {\r
++      struct squashfs_base_inode_header_2     base;\r
++      struct squashfs_dev_inode_header_2      dev;\r
++      struct squashfs_symlink_inode_header_2  symlink;\r
++      struct squashfs_reg_inode_header_2      reg;\r
++      struct squashfs_dir_inode_header_2      dir;\r
++      struct squashfs_ldir_inode_header_2     ldir;\r
++      struct squashfs_ipc_inode_header_2      ipc;\r
++};\r
++      \r
++struct squashfs_dir_header_2 {\r
++      unsigned int            count:8;\r
++      unsigned int            start_block:24;\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dir_entry_2 {\r
++      unsigned int            offset:13;\r
++      unsigned int            type:3;\r
++      unsigned int            size:8;\r
++      char                    name[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_fragment_entry_2 {\r
++      unsigned int            start_block;\r
++      unsigned int            size;\r
++} __attribute__ ((packed));\r
++\r
++#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\\r
++      SQUASHFS_MEMSET(s, d, n);\\r
++      SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\\r
++      SQUASHFS_SWAP((s)->mode, d, 4, 12);\\r
++      SQUASHFS_SWAP((s)->uid, d, 16, 8);\\r
++      SQUASHFS_SWAP((s)->guid, d, 24, 8);\\r
++\r
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\\r
++}\r
++\r
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \\r
++      SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))\r
++\r
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
++                      sizeof(struct squashfs_dev_inode_header_2)); \\r
++      SQUASHFS_SWAP((s)->rdev, d, 32, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
++                      sizeof(struct squashfs_symlink_inode_header_2));\\r
++      SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
++                      sizeof(struct squashfs_reg_inode_header_2));\\r
++      SQUASHFS_SWAP((s)->mtime, d, 32, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 64, 32);\\r
++      SQUASHFS_SWAP((s)->fragment, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->offset, d, 128, 32);\\r
++      SQUASHFS_SWAP((s)->file_size, d, 160, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
++                      sizeof(struct squashfs_dir_inode_header_2));\\r
++      SQUASHFS_SWAP((s)->file_size, d, 32, 19);\\r
++      SQUASHFS_SWAP((s)->offset, d, 51, 13);\\r
++      SQUASHFS_SWAP((s)->mtime, d, 64, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 96, 24);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
++                      sizeof(struct squashfs_ldir_inode_header_2));\\r
++      SQUASHFS_SWAP((s)->file_size, d, 32, 27);\\r
++      SQUASHFS_SWAP((s)->offset, d, 59, 13);\\r
++      SQUASHFS_SWAP((s)->mtime, d, 72, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 104, 24);\\r
++      SQUASHFS_SWAP((s)->i_count, d, 128, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\\r
++      SQUASHFS_SWAP((s)->index, d, 0, 27);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 27, 29);\\r
++      SQUASHFS_SWAP((s)->size, d, 56, 8);\\r
++}\r
++#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\\r
++      SQUASHFS_SWAP((s)->count, d, 0, 8);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 8, 24);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\\r
++      SQUASHFS_SWAP((s)->offset, d, 0, 13);\\r
++      SQUASHFS_SWAP((s)->type, d, 13, 3);\\r
++      SQUASHFS_SWAP((s)->size, d, 16, 8);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\\r
++      SQUASHFS_SWAP((s)->start_block, d, 0, 32);\\r
++      SQUASHFS_SWAP((s)->size, d, 32, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)\r
++\r
++/* fragment and fragment table defines */\r
++#define SQUASHFS_FRAGMENT_BYTES_2(A)  (A * sizeof(struct squashfs_fragment_entry_2))\r
++\r
++#define SQUASHFS_FRAGMENT_INDEX_2(A)  (SQUASHFS_FRAGMENT_BYTES_2(A) / \\r
++                                      SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A)   (SQUASHFS_FRAGMENT_BYTES_2(A) % \\r
++                                              SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_FRAGMENT_INDEXES_2(A)        ((SQUASHFS_FRAGMENT_BYTES_2(A) + \\r
++                                      SQUASHFS_METADATA_SIZE - 1) / \\r
++                                      SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A)    (SQUASHFS_FRAGMENT_INDEXES_2(A) *\\r
++                                              sizeof(int))\r
++\r
++#endif\r
++\r
++#ifdef __KERNEL__\r
++\r
++/*\r
++ * macros used to swap each structure entry, taking into account\r
++ * bitfields and different bitfield placing conventions on differing\r
++ * architectures\r
++ */\r
++\r
++#include <asm/byteorder.h>\r
++\r
++#ifdef __BIG_ENDIAN\r
++      /* convert from little endian to big endian */\r
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \\r
++              tbits, b_pos)\r
++#else\r
++      /* convert from big endian to little endian */ \r
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \\r
++              tbits, 64 - tbits - b_pos)\r
++#endif\r
++\r
++#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\\r
++      b_pos = pos % 8;\\r
++      val = 0;\\r
++      s = (unsigned char *)p + (pos / 8);\\r
++      d = ((unsigned char *) &val) + 7;\\r
++      for(bits = 0; bits < (tbits + b_pos); bits += 8) \\r
++              *d-- = *s++;\\r
++      value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\\r
++}\r
++\r
++#define SQUASHFS_MEMSET(s, d, n)      memset(s, 0, n);\r
++\r
++#endif\r
++#endif\r
+diff -urN linux-2.6.23/include/linux/squashfs_fs_i.h linux-2.6.23.sqlzma/include/linux/squashfs_fs_i.h\r
+--- linux-2.6.23/include/linux/squashfs_fs_i.h 1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/include/linux/squashfs_fs_i.h  2007-10-14 10:24:31.000000000 -0400\r
+@@ -0,0 +1,45 @@\r
++#ifndef SQUASHFS_FS_I\r
++#define SQUASHFS_FS_I\r
++/*\r
++ * Squashfs\r
++ *\r
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
++ * Phillip Lougher <phillip@lougher.org.uk>\r
++ *\r
++ * This program is free software; you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License\r
++ * as published by the Free Software Foundation; either version 2,\r
++ * or (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program; if not, write to the Free Software\r
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
++ *\r
++ * squashfs_fs_i.h\r
++ */\r
++\r
++struct squashfs_inode_info {\r
++      long long       start_block;\r
++      unsigned int    offset;\r
++      union {\r
++              struct {\r
++                      long long       fragment_start_block;\r
++                      unsigned int    fragment_size;\r
++                      unsigned int    fragment_offset;\r
++                      long long       block_list_start;\r
++              } s1;\r
++              struct {\r
++                      long long       directory_index_start;\r
++                      unsigned int    directory_index_offset;\r
++                      unsigned int    directory_index_count;\r
++                      unsigned int    parent_inode;\r
++              } s2;\r
++      } u;\r
++      struct inode    vfs_inode;\r
++};\r
++#endif\r
+diff -urN linux-2.6.23/include/linux/squashfs_fs_sb.h linux-2.6.23.sqlzma/include/linux/squashfs_fs_sb.h\r
+--- linux-2.6.23/include/linux/squashfs_fs_sb.h        1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/include/linux/squashfs_fs_sb.h 2007-10-14 14:32:50.000000000 -0400\r
+@@ -0,0 +1,73 @@\r
++#ifndef SQUASHFS_FS_SB\r
++#define SQUASHFS_FS_SB\r
++/*\r
++ * Squashfs\r
++ *\r
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
++ * Phillip Lougher <phillip@lougher.org.uk>\r
++ *\r
++ * This program is free software; you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License\r
++ * as published by the Free Software Foundation; either version 2,\r
++ * or (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program; if not, write to the Free Software\r
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
++ *\r
++ * squashfs_fs_sb.h\r
++ */\r
++\r
++#include <linux/squashfs_fs.h>\r
++\r
++struct squashfs_cache {\r
++      long long       block;\r
++      int             length;\r
++      long long       next_index;\r
++      char            *data;\r
++};\r
++\r
++struct squashfs_fragment_cache {\r
++      long long       block;\r
++      int             length;\r
++      unsigned int    locked;\r
++      char            *data;\r
++};\r
++\r
++struct squashfs_sb_info {\r
++      struct squashfs_super_block     sblk;\r
++      int                     devblksize;\r
++      int                     devblksize_log2;\r
++      int                     swap;\r
++      struct squashfs_cache   *block_cache;\r
++      struct squashfs_fragment_cache  *fragment;\r
++      int                     next_cache;\r
++      int                     next_fragment;\r
++      int                     next_meta_index;\r
++      unsigned int            *uid;\r
++      unsigned int            *guid;\r
++      long long               *fragment_index;\r
++      unsigned int            *fragment_index_2;\r
++      char                    *read_page;\r
++      //struct mutex          read_data_mutex;\r
++      struct mutex            read_page_mutex;\r
++      struct mutex            block_cache_mutex;\r
++      struct mutex            fragment_mutex;\r
++      struct mutex            meta_index_mutex;\r
++      wait_queue_head_t       waitq;\r
++      wait_queue_head_t       fragment_wait_queue;\r
++      struct meta_index       *meta_index;\r
++      long long               *inode_lookup_table;\r
++      int                     (*read_inode)(struct inode *i,  squashfs_inode_t \\r
++                              inode);\r
++      long long               (*read_blocklist)(struct inode *inode, int \\r
++                              index, int readahead_blks, char *block_list, \\r
++                              unsigned short **block_p, unsigned int *bsize);\r
++      int                     (*read_fragment_index_table)(struct super_block *s);\r
++};\r
++#endif\r
+diff -urN linux-2.6.23/init/do_mounts_rd.c linux-2.6.23.sqlzma/init/do_mounts_rd.c\r
+--- linux-2.6.23/init/do_mounts_rd.c   2007-10-09 16:31:38.000000000 -0400\r
++++ linux-2.6.23.sqlzma/init/do_mounts_rd.c    2007-10-14 10:24:31.000000000 -0400\r
+@@ -5,6 +5,7 @@\r
+ #include <linux/ext2_fs.h>\r
+ #include <linux/romfs_fs.h>\r
+ #include <linux/cramfs_fs.h>\r
++#include <linux/squashfs_fs.h>\r
+ #include <linux/initrd.h>\r
+ #include <linux/string.h>\r
\r
+@@ -39,6 +40,7 @@\r
+  * numbers could not be found.\r
+  *\r
+  * We currently check for the following magic numbers:\r
++ *      squashfs\r
+  *    minix\r
+  *    ext2\r
+  *    romfs\r
+@@ -53,6 +55,7 @@\r
+       struct ext2_super_block *ext2sb;\r
+       struct romfs_super_block *romfsb;\r
+       struct cramfs_super *cramfsb;\r
++      struct squashfs_super_block *squashfsb;\r
+       int nblocks = -1;\r
+       unsigned char *buf;\r
\r
+@@ -64,6 +67,7 @@\r
+       ext2sb = (struct ext2_super_block *) buf;\r
+       romfsb = (struct romfs_super_block *) buf;\r
+       cramfsb = (struct cramfs_super *) buf;\r
++      squashfsb = (struct squashfs_super_block *) buf;\r
+       memset(buf, 0xe5, size);\r
\r
+       /*\r
+@@ -101,6 +105,18 @@\r
+               goto done;\r
+       }\r
\r
++      /* squashfs is at block zero too */\r
++      if (squashfsb->s_magic == SQUASHFS_MAGIC) {\r
++              printk(KERN_NOTICE\r
++                     "RAMDISK: squashfs filesystem found at block %d\n",\r
++                     start_block);\r
++              if (squashfsb->s_major < 3)\r
++                      nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;\r
++              else\r
++                      nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;\r
++              goto done;\r
++      }\r
++\r
+       /*\r
+        * Read block 1 to test for minix and ext2 superblock\r
+        */\r
diff --git a/recipes/linux/linux-rt-2.6.24/squashfs-lzma-2.6.24.patch b/recipes/linux/linux-rt-2.6.24/squashfs-lzma-2.6.24.patch
new file mode 100644 (file)
index 0000000..fb92cbf
--- /dev/null
@@ -0,0 +1,5621 @@
+diff -urN linux-2.6.23/fs/Kconfig linux-2.6.23.sqlzma/fs/Kconfig\r
+--- linux-2.6.23/fs/Kconfig    2007-10-09 16:31:38.000000000 -0400\r
++++ linux-2.6.23.sqlzma/fs/Kconfig     2007-10-14 13:19:21.000000000 -0400\r
+@@ -1364,6 +1364,72 @@\r
\r
+         If unsure, say N.\r
\r
++config SQUASHFS\r
++      tristate "SquashFS 3.2 - Squashed file system support"\r
++      select ZLIB_INFLATE\r
++      help\r
++        Saying Y here includes support for SquashFS 3.2 (a Compressed Read-\r
++        Only File System).  Squashfs is a highly compressed read-only\r
++        filesystem for Linux.  It uses zlib and/or LZMA compression to compress\r
++        both files, inodes and directories.  Inodes in the system are very\r
++        small and all blocks are packed to minimise data overhead. Block sizes\r
++        greater than 4K are supported up to a maximum of 64K.  SquashFS 3.2\r
++        supports 64 bit filesystems and files (larger than 4GB), full uid/gid\r
++        information, hard links and timestamps.\r
++\r
++        Squashfs is intended for general read-only filesystem use, for archival\r
++        use (i.e. in cases where a .tar.gz file may be used), and in embedded\r
++        systems where low overhead is needed.  Further information and\r
++        filesystem tools are available from http://squashfs.sourceforge.net.\r
++\r
++        If you want to compile this as a module ( = code which can be\r
++        inserted in and removed from the running kernel whenever you want),\r
++        say M here and read <file:Documentation/modules.txt>.  The module\r
++        will be called squashfs.  Note that the root file system (the one\r
++        containing the directory /) cannot be compiled as a module.\r
++\r
++        If unsure, say N.\r
++\r
++config SQUASHFS_EMBEDDED\r
++\r
++      bool "Additional options for memory-constrained systems" \r
++      depends on SQUASHFS\r
++      default n\r
++      help\r
++        Saying Y here allows you to specify cache sizes and how Squashfs\r
++        allocates memory.  This is only intended for memory constrained\r
++        systems.\r
++\r
++        If unsure, say N.\r
++\r
++config SQUASHFS_FRAGMENT_CACHE_SIZE\r
++      int "Number of fragments cached" if SQUASHFS_EMBEDDED\r
++      depends on SQUASHFS\r
++      default "3"\r
++      help\r
++        By default SquashFS caches the last 3 fragments read from\r
++        the filesystem.  Increasing this amount may mean SquashFS\r
++        has to re-read fragments less often from disk, at the expense\r
++        of extra system memory.  Decreasing this amount will mean\r
++        SquashFS uses less memory at the expense of extra reads from disk.\r
++\r
++        Note there must be at least one cached fragment.  Anything\r
++        much more than three will probably not make much difference.\r
++\r
++config SQUASHFS_VMALLOC\r
++      bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED\r
++      depends on SQUASHFS\r
++      default n\r
++      help\r
++        By default SquashFS uses kmalloc to obtain fragment cache memory.\r
++        Kmalloc memory is the standard kernel allocator, but it can fail\r
++        on memory constrained systems.  Because of the way Vmalloc works,\r
++        Vmalloc can succeed when kmalloc fails.  Specifying this option\r
++        will make SquashFS always use Vmalloc to allocate the\r
++        fragment cache memory.\r
++\r
++        If unsure, say N.\r
++\r
+ config VXFS_FS\r
+       tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"\r
+       depends on BLOCK\r
+diff -urN linux-2.6.23/fs/Makefile linux-2.6.23.sqlzma/fs/Makefile\r
+--- linux-2.6.23/fs/Makefile   2007-10-09 16:31:38.000000000 -0400\r
++++ linux-2.6.23.sqlzma/fs/Makefile    2007-10-14 10:24:31.000000000 -0400\r
+@@ -72,6 +72,7 @@\r
+ obj-$(CONFIG_JBD2)            += jbd2/\r
+ obj-$(CONFIG_EXT2_FS)         += ext2/\r
+ obj-$(CONFIG_CRAMFS)          += cramfs/\r
++obj-$(CONFIG_SQUASHFS)                += squashfs/\r
+ obj-y                         += ramfs/\r
+ obj-$(CONFIG_HUGETLBFS)               += hugetlbfs/\r
+ obj-$(CONFIG_CODA_FS)         += coda/\r
+diff -urN linux-2.6.23/fs/squashfs/LzmaDecode.c linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.c\r
+--- linux-2.6.23/fs/squashfs/LzmaDecode.c      1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.c       2007-10-14 12:44:42.000000000 -0400\r
+@@ -0,0 +1,584 @@\r
++/*\r
++  LzmaDecode.c\r
++  LZMA Decoder (optimized for Speed version)\r
++  \r
++  LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)\r
++  http://www.7-zip.org/\r
++\r
++  LZMA SDK is licensed under two licenses:\r
++  1) GNU Lesser General Public License (GNU LGPL)\r
++  2) Common Public License (CPL)\r
++  It means that you can select one of these two licenses and \r
++  follow rules of that license.\r
++\r
++  SPECIAL EXCEPTION:\r
++  Igor Pavlov, as the author of this Code, expressly permits you to \r
++  statically or dynamically link your Code (or bind by name) to the \r
++  interfaces of this file without subjecting your linked Code to the \r
++  terms of the CPL or GNU LGPL. Any modifications or additions \r
++  to this file, however, are subject to the LGPL or CPL terms.\r
++*/\r
++\r
++#include "LzmaDecode.h"\r
++\r
++#define kNumTopBits 24\r
++#define kTopValue ((UInt32)1 << kNumTopBits)\r
++\r
++#define kNumBitModelTotalBits 11\r
++#define kBitModelTotal (1 << kNumBitModelTotalBits)\r
++#define kNumMoveBits 5\r
++\r
++#define RC_READ_BYTE (*Buffer++)\r
++\r
++#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \\r
++  { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}\r
++\r
++#ifdef _LZMA_IN_CB\r
++\r
++#define RC_TEST { if (Buffer == BufferLim) \\r
++  { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \\r
++  BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}\r
++\r
++#define RC_INIT Buffer = BufferLim = 0; RC_INIT2\r
++\r
++#else\r
++\r
++#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }\r
++\r
++#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2\r
++ \r
++#endif\r
++\r
++#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }\r
++\r
++#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)\r
++#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;\r
++#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;\r
++\r
++#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \\r
++  { UpdateBit0(p); mi <<= 1; A0; } else \\r
++  { UpdateBit1(p); mi = (mi + mi) + 1; A1; } \r
++  \r
++#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)               \r
++\r
++#define RangeDecoderBitTreeDecode(probs, numLevels, res) \\r
++  { int i = numLevels; res = 1; \\r
++  do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \\r
++  res -= (1 << numLevels); }\r
++\r
++\r
++#define kNumPosBitsMax 4\r
++#define kNumPosStatesMax (1 << kNumPosBitsMax)\r
++\r
++#define kLenNumLowBits 3\r
++#define kLenNumLowSymbols (1 << kLenNumLowBits)\r
++#define kLenNumMidBits 3\r
++#define kLenNumMidSymbols (1 << kLenNumMidBits)\r
++#define kLenNumHighBits 8\r
++#define kLenNumHighSymbols (1 << kLenNumHighBits)\r
++\r
++#define LenChoice 0\r
++#define LenChoice2 (LenChoice + 1)\r
++#define LenLow (LenChoice2 + 1)\r
++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))\r
++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))\r
++#define kNumLenProbs (LenHigh + kLenNumHighSymbols) \r
++\r
++\r
++#define kNumStates 12\r
++#define kNumLitStates 7\r
++\r
++#define kStartPosModelIndex 4\r
++#define kEndPosModelIndex 14\r
++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))\r
++\r
++#define kNumPosSlotBits 6\r
++#define kNumLenToPosStates 4\r
++\r
++#define kNumAlignBits 4\r
++#define kAlignTableSize (1 << kNumAlignBits)\r
++\r
++#define kMatchMinLen 2\r
++\r
++#define IsMatch 0\r
++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))\r
++#define IsRepG0 (IsRep + kNumStates)\r
++#define IsRepG1 (IsRepG0 + kNumStates)\r
++#define IsRepG2 (IsRepG1 + kNumStates)\r
++#define IsRep0Long (IsRepG2 + kNumStates)\r
++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))\r
++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))\r
++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)\r
++#define LenCoder (Align + kAlignTableSize)\r
++#define RepLenCoder (LenCoder + kNumLenProbs)\r
++#define Literal (RepLenCoder + kNumLenProbs)\r
++\r
++#if Literal != LZMA_BASE_SIZE\r
++StopCompilingDueBUG\r
++#endif\r
++\r
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)\r
++{\r
++  unsigned char prop0;\r
++  if (size < LZMA_PROPERTIES_SIZE)\r
++    return LZMA_RESULT_DATA_ERROR;\r
++  prop0 = propsData[0];\r
++  if (prop0 >= (9 * 5 * 5))\r
++    return LZMA_RESULT_DATA_ERROR;\r
++  {\r
++    for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));\r
++    for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);\r
++    propsRes->lc = prop0;\r
++    /*\r
++    unsigned char remainder = (unsigned char)(prop0 / 9);\r
++    propsRes->lc = prop0 % 9;\r
++    propsRes->pb = remainder / 5;\r
++    propsRes->lp = remainder % 5;\r
++    */\r
++  }\r
++\r
++  #ifdef _LZMA_OUT_READ\r
++  {\r
++    int i;\r
++    propsRes->DictionarySize = 0;\r
++    for (i = 0; i < 4; i++)\r
++      propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);\r
++    if (propsRes->DictionarySize == 0)\r
++      propsRes->DictionarySize = 1;\r
++  }\r
++  #endif\r
++  return LZMA_RESULT_OK;\r
++}\r
++\r
++#define kLzmaStreamWasFinishedId (-1)\r
++\r
++int LzmaDecode(CLzmaDecoderState *vs,\r
++    #ifdef _LZMA_IN_CB\r
++    ILzmaInCallback *InCallback,\r
++    #else\r
++    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,\r
++    #endif\r
++    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)\r
++{\r
++  CProb *p = vs->Probs;\r
++  SizeT nowPos = 0;\r
++  Byte previousByte = 0;\r
++  UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;\r
++  UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;\r
++  int lc = vs->Properties.lc;\r
++\r
++  #ifdef _LZMA_OUT_READ\r
++  \r
++  UInt32 Range = vs->Range;\r
++  UInt32 Code = vs->Code;\r
++  #ifdef _LZMA_IN_CB\r
++  const Byte *Buffer = vs->Buffer;\r
++  const Byte *BufferLim = vs->BufferLim;\r
++  #else\r
++  const Byte *Buffer = inStream;\r
++  const Byte *BufferLim = inStream + inSize;\r
++  #endif\r
++  int state = vs->State;\r
++  UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];\r
++  int len = vs->RemainLen;\r
++  UInt32 globalPos = vs->GlobalPos;\r
++  UInt32 distanceLimit = vs->DistanceLimit;\r
++\r
++  Byte *dictionary = vs->Dictionary;\r
++  UInt32 dictionarySize = vs->Properties.DictionarySize;\r
++  UInt32 dictionaryPos = vs->DictionaryPos;\r
++\r
++  Byte tempDictionary[4];\r
++\r
++  #ifndef _LZMA_IN_CB\r
++  *inSizeProcessed = 0;\r
++  #endif\r
++  *outSizeProcessed = 0;\r
++  if (len == kLzmaStreamWasFinishedId)\r
++    return LZMA_RESULT_OK;\r
++\r
++  if (dictionarySize == 0)\r
++  {\r
++    dictionary = tempDictionary;\r
++    dictionarySize = 1;\r
++    tempDictionary[0] = vs->TempDictionary[0];\r
++  }\r
++\r
++  if (len == kLzmaNeedInitId)\r
++  {\r
++    {\r
++      UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));\r
++      UInt32 i;\r
++      for (i = 0; i < numProbs; i++)\r
++        p[i] = kBitModelTotal >> 1; \r
++      rep0 = rep1 = rep2 = rep3 = 1;\r
++      state = 0;\r
++      globalPos = 0;\r
++      distanceLimit = 0;\r
++      dictionaryPos = 0;\r
++      dictionary[dictionarySize - 1] = 0;\r
++      #ifdef _LZMA_IN_CB\r
++      RC_INIT;\r
++      #else\r
++      RC_INIT(inStream, inSize);\r
++      #endif\r
++    }\r
++    len = 0;\r
++  }\r
++  while(len != 0 && nowPos < outSize)\r
++  {\r
++    UInt32 pos = dictionaryPos - rep0;\r
++    if (pos >= dictionarySize)\r
++      pos += dictionarySize;\r
++    outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];\r
++    if (++dictionaryPos == dictionarySize)\r
++      dictionaryPos = 0;\r
++    len--;\r
++  }\r
++  if (dictionaryPos == 0)\r
++    previousByte = dictionary[dictionarySize - 1];\r
++  else\r
++    previousByte = dictionary[dictionaryPos - 1];\r
++\r
++  #else /* if !_LZMA_OUT_READ */\r
++\r
++  int state = 0;\r
++  UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;\r
++  int len = 0;\r
++  const Byte *Buffer;\r
++  const Byte *BufferLim;\r
++  UInt32 Range;\r
++  UInt32 Code;\r
++\r
++  #ifndef _LZMA_IN_CB\r
++  *inSizeProcessed = 0;\r
++  #endif\r
++  *outSizeProcessed = 0;\r
++\r
++  {\r
++    UInt32 i;\r
++    UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));\r
++    for (i = 0; i < numProbs; i++)\r
++      p[i] = kBitModelTotal >> 1;\r
++  }\r
++  \r
++  #ifdef _LZMA_IN_CB\r
++  RC_INIT;\r
++  #else\r
++  RC_INIT(inStream, inSize);\r
++  #endif\r
++\r
++  #endif /* _LZMA_OUT_READ */\r
++\r
++  while(nowPos < outSize)\r
++  {\r
++    CProb *prob;\r
++    UInt32 bound;\r
++    int posState = (int)(\r
++        (nowPos \r
++        #ifdef _LZMA_OUT_READ\r
++        + globalPos\r
++        #endif\r
++        )\r
++        & posStateMask);\r
++\r
++    prob = p + IsMatch + (state << kNumPosBitsMax) + posState;\r
++    IfBit0(prob)\r
++    {\r
++      int symbol = 1;\r
++      UpdateBit0(prob)\r
++      prob = p + Literal + (LZMA_LIT_SIZE * \r
++        (((\r
++        (nowPos \r
++        #ifdef _LZMA_OUT_READ\r
++        + globalPos\r
++        #endif\r
++        )\r
++        & literalPosMask) << lc) + (previousByte >> (8 - lc))));\r
++\r
++      if (state >= kNumLitStates)\r
++      {\r
++        int matchByte;\r
++        #ifdef _LZMA_OUT_READ\r
++        UInt32 pos = dictionaryPos - rep0;\r
++        if (pos >= dictionarySize)\r
++          pos += dictionarySize;\r
++        matchByte = dictionary[pos];\r
++        #else\r
++        matchByte = outStream[nowPos - rep0];\r
++        #endif\r
++        do\r
++        {\r
++          int bit;\r
++          CProb *probLit;\r
++          matchByte <<= 1;\r
++          bit = (matchByte & 0x100);\r
++          probLit = prob + 0x100 + bit + symbol;\r
++          RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)\r
++        }\r
++        while (symbol < 0x100);\r
++      }\r
++      while (symbol < 0x100)\r
++      {\r
++        CProb *probLit = prob + symbol;\r
++        RC_GET_BIT(probLit, symbol)\r
++      }\r
++      previousByte = (Byte)symbol;\r
++\r
++      outStream[nowPos++] = previousByte;\r
++      #ifdef _LZMA_OUT_READ\r
++      if (distanceLimit < dictionarySize)\r
++        distanceLimit++;\r
++\r
++      dictionary[dictionaryPos] = previousByte;\r
++      if (++dictionaryPos == dictionarySize)\r
++        dictionaryPos = 0;\r
++      #endif\r
++      if (state < 4) state = 0;\r
++      else if (state < 10) state -= 3;\r
++      else state -= 6;\r
++    }\r
++    else             \r
++    {\r
++      UpdateBit1(prob);\r
++      prob = p + IsRep + state;\r
++      IfBit0(prob)\r
++      {\r
++        UpdateBit0(prob);\r
++        rep3 = rep2;\r
++        rep2 = rep1;\r
++        rep1 = rep0;\r
++        state = state < kNumLitStates ? 0 : 3;\r
++        prob = p + LenCoder;\r
++      }\r
++      else\r
++      {\r
++        UpdateBit1(prob);\r
++        prob = p + IsRepG0 + state;\r
++        IfBit0(prob)\r
++        {\r
++          UpdateBit0(prob);\r
++          prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;\r
++          IfBit0(prob)\r
++          {\r
++            #ifdef _LZMA_OUT_READ\r
++            UInt32 pos;\r
++            #endif\r
++            UpdateBit0(prob);\r
++            \r
++            #ifdef _LZMA_OUT_READ\r
++            if (distanceLimit == 0)\r
++            #else\r
++            if (nowPos == 0)\r
++            #endif\r
++              return LZMA_RESULT_DATA_ERROR;\r
++            \r
++            state = state < kNumLitStates ? 9 : 11;\r
++            #ifdef _LZMA_OUT_READ\r
++            pos = dictionaryPos - rep0;\r
++            if (pos >= dictionarySize)\r
++              pos += dictionarySize;\r
++            previousByte = dictionary[pos];\r
++            dictionary[dictionaryPos] = previousByte;\r
++            if (++dictionaryPos == dictionarySize)\r
++              dictionaryPos = 0;\r
++            #else\r
++            previousByte = outStream[nowPos - rep0];\r
++            #endif\r
++            outStream[nowPos++] = previousByte;\r
++            #ifdef _LZMA_OUT_READ\r
++            if (distanceLimit < dictionarySize)\r
++              distanceLimit++;\r
++            #endif\r
++\r
++            continue;\r
++          }\r
++          else\r
++          {\r
++            UpdateBit1(prob);\r
++          }\r
++        }\r
++        else\r
++        {\r
++          UInt32 distance;\r
++          UpdateBit1(prob);\r
++          prob = p + IsRepG1 + state;\r
++          IfBit0(prob)\r
++          {\r
++            UpdateBit0(prob);\r
++            distance = rep1;\r
++          }\r
++          else \r
++          {\r
++            UpdateBit1(prob);\r
++            prob = p + IsRepG2 + state;\r
++            IfBit0(prob)\r
++            {\r
++              UpdateBit0(prob);\r
++              distance = rep2;\r
++            }\r
++            else\r
++            {\r
++              UpdateBit1(prob);\r
++              distance = rep3;\r
++              rep3 = rep2;\r
++            }\r
++            rep2 = rep1;\r
++          }\r
++          rep1 = rep0;\r
++          rep0 = distance;\r
++        }\r
++        state = state < kNumLitStates ? 8 : 11;\r
++        prob = p + RepLenCoder;\r
++      }\r
++      {\r
++        int numBits, offset;\r
++        CProb *probLen = prob + LenChoice;\r
++        IfBit0(probLen)\r
++        {\r
++          UpdateBit0(probLen);\r
++          probLen = prob + LenLow + (posState << kLenNumLowBits);\r
++          offset = 0;\r
++          numBits = kLenNumLowBits;\r
++        }\r
++        else\r
++        {\r
++          UpdateBit1(probLen);\r
++          probLen = prob + LenChoice2;\r
++          IfBit0(probLen)\r
++          {\r
++            UpdateBit0(probLen);\r
++            probLen = prob + LenMid + (posState << kLenNumMidBits);\r
++            offset = kLenNumLowSymbols;\r
++            numBits = kLenNumMidBits;\r
++          }\r
++          else\r
++          {\r
++            UpdateBit1(probLen);\r
++            probLen = prob + LenHigh;\r
++            offset = kLenNumLowSymbols + kLenNumMidSymbols;\r
++            numBits = kLenNumHighBits;\r
++          }\r
++        }\r
++        RangeDecoderBitTreeDecode(probLen, numBits, len);\r
++        len += offset;\r
++      }\r
++\r
++      if (state < 4)\r
++      {\r
++        int posSlot;\r
++        state += kNumLitStates;\r
++        prob = p + PosSlot +\r
++            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << \r
++            kNumPosSlotBits);\r
++        RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);\r
++        if (posSlot >= kStartPosModelIndex)\r
++        {\r
++          int numDirectBits = ((posSlot >> 1) - 1);\r
++          rep0 = (2 | ((UInt32)posSlot & 1));\r
++          if (posSlot < kEndPosModelIndex)\r
++          {\r
++            rep0 <<= numDirectBits;\r
++            prob = p + SpecPos + rep0 - posSlot - 1;\r
++          }\r
++          else\r
++          {\r
++            numDirectBits -= kNumAlignBits;\r
++            do\r
++            {\r
++              RC_NORMALIZE\r
++              Range >>= 1;\r
++              rep0 <<= 1;\r
++              if (Code >= Range)\r
++              {\r
++                Code -= Range;\r
++                rep0 |= 1;\r
++              }\r
++            }\r
++            while (--numDirectBits != 0);\r
++            prob = p + Align;\r
++            rep0 <<= kNumAlignBits;\r
++            numDirectBits = kNumAlignBits;\r
++          }\r
++          {\r
++            int i = 1;\r
++            int mi = 1;\r
++            do\r
++            {\r
++              CProb *prob3 = prob + mi;\r
++              RC_GET_BIT2(prob3, mi, ; , rep0 |= i);\r
++              i <<= 1;\r
++            }\r
++            while(--numDirectBits != 0);\r
++          }\r
++        }\r
++        else\r
++          rep0 = posSlot;\r
++        if (++rep0 == (UInt32)(0))\r
++        {\r
++          /* it's for stream version */\r
++          len = kLzmaStreamWasFinishedId;\r
++          break;\r
++        }\r
++      }\r
++\r
++      len += kMatchMinLen;\r
++      #ifdef _LZMA_OUT_READ\r
++      if (rep0 > distanceLimit) \r
++      #else\r
++      if (rep0 > nowPos)\r
++      #endif\r
++        return LZMA_RESULT_DATA_ERROR;\r
++\r
++      #ifdef _LZMA_OUT_READ\r
++      if (dictionarySize - distanceLimit > (UInt32)len)\r
++        distanceLimit += len;\r
++      else\r
++        distanceLimit = dictionarySize;\r
++      #endif\r
++\r
++      do\r
++      {\r
++        #ifdef _LZMA_OUT_READ\r
++        UInt32 pos = dictionaryPos - rep0;\r
++        if (pos >= dictionarySize)\r
++          pos += dictionarySize;\r
++        previousByte = dictionary[pos];\r
++        dictionary[dictionaryPos] = previousByte;\r
++        if (++dictionaryPos == dictionarySize)\r
++          dictionaryPos = 0;\r
++        #else\r
++        previousByte = outStream[nowPos - rep0];\r
++        #endif\r
++        len--;\r
++        outStream[nowPos++] = previousByte;\r
++      }\r
++      while(len != 0 && nowPos < outSize);\r
++    }\r
++  }\r
++  RC_NORMALIZE;\r
++\r
++  #ifdef _LZMA_OUT_READ\r
++  vs->Range = Range;\r
++  vs->Code = Code;\r
++  vs->DictionaryPos = dictionaryPos;\r
++  vs->GlobalPos = globalPos + (UInt32)nowPos;\r
++  vs->DistanceLimit = distanceLimit;\r
++  vs->Reps[0] = rep0;\r
++  vs->Reps[1] = rep1;\r
++  vs->Reps[2] = rep2;\r
++  vs->Reps[3] = rep3;\r
++  vs->State = state;\r
++  vs->RemainLen = len;\r
++  vs->TempDictionary[0] = tempDictionary[0];\r
++  #endif\r
++\r
++  #ifdef _LZMA_IN_CB\r
++  vs->Buffer = Buffer;\r
++  vs->BufferLim = BufferLim;\r
++  #else\r
++  *inSizeProcessed = (SizeT)(Buffer - inStream);\r
++  #endif\r
++  *outSizeProcessed = nowPos;\r
++  return LZMA_RESULT_OK;\r
++}\r
+diff -urN linux-2.6.23/fs/squashfs/LzmaDecode.h linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.h\r
+--- linux-2.6.23/fs/squashfs/LzmaDecode.h      1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.h       2007-10-14 12:44:42.000000000 -0400\r
+@@ -0,0 +1,113 @@\r
++/* \r
++  LzmaDecode.h\r
++  LZMA Decoder interface\r
++\r
++  LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)\r
++  http://www.7-zip.org/\r
++\r
++  LZMA SDK is licensed under two licenses:\r
++  1) GNU Lesser General Public License (GNU LGPL)\r
++  2) Common Public License (CPL)\r
++  It means that you can select one of these two licenses and \r
++  follow rules of that license.\r
++\r
++  SPECIAL EXCEPTION:\r
++  Igor Pavlov, as the author of this code, expressly permits you to \r
++  statically or dynamically link your code (or bind by name) to the \r
++  interfaces of this file without subjecting your linked code to the \r
++  terms of the CPL or GNU LGPL. Any modifications or additions \r
++  to this file, however, are subject to the LGPL or CPL terms.\r
++*/\r
++\r
++#ifndef __LZMADECODE_H\r
++#define __LZMADECODE_H\r
++\r
++#include "LzmaTypes.h"\r
++\r
++/* #define _LZMA_IN_CB */\r
++/* Use callback for input data */\r
++\r
++/* #define _LZMA_OUT_READ */\r
++/* Use read function for output data */\r
++\r
++/* #define _LZMA_PROB32 */\r
++/* It can increase speed on some 32-bit CPUs, \r
++   but memory usage will be doubled in that case */\r
++\r
++/* #define _LZMA_LOC_OPT */\r
++/* Enable local speed optimizations inside code */\r
++\r
++#ifdef _LZMA_PROB32\r
++#define CProb UInt32\r
++#else\r
++#define CProb UInt16\r
++#endif\r
++\r
++#define LZMA_RESULT_OK 0\r
++#define LZMA_RESULT_DATA_ERROR 1\r
++\r
++#ifdef _LZMA_IN_CB\r
++typedef struct _ILzmaInCallback\r
++{\r
++  int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);\r
++} ILzmaInCallback;\r
++#endif\r
++\r
++#define LZMA_BASE_SIZE 1846\r
++#define LZMA_LIT_SIZE 768\r
++\r
++#define LZMA_PROPERTIES_SIZE 5\r
++\r
++typedef struct _CLzmaProperties\r
++{\r
++  int lc;\r
++  int lp;\r
++  int pb;\r
++  #ifdef _LZMA_OUT_READ\r
++  UInt32 DictionarySize;\r
++  #endif\r
++}CLzmaProperties;\r
++\r
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);\r
++\r
++#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))\r
++\r
++#define kLzmaNeedInitId (-2)\r
++\r
++typedef struct _CLzmaDecoderState\r
++{\r
++  CLzmaProperties Properties;\r
++  CProb *Probs;\r
++\r
++  #ifdef _LZMA_IN_CB\r
++  const unsigned char *Buffer;\r
++  const unsigned char *BufferLim;\r
++  #endif\r
++\r
++  #ifdef _LZMA_OUT_READ\r
++  unsigned char *Dictionary;\r
++  UInt32 Range;\r
++  UInt32 Code;\r
++  UInt32 DictionaryPos;\r
++  UInt32 GlobalPos;\r
++  UInt32 DistanceLimit;\r
++  UInt32 Reps[4];\r
++  int State;\r
++  int RemainLen;\r
++  unsigned char TempDictionary[4];\r
++  #endif\r
++} CLzmaDecoderState;\r
++\r
++#ifdef _LZMA_OUT_READ\r
++#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }\r
++#endif\r
++\r
++int LzmaDecode(CLzmaDecoderState *vs,\r
++    #ifdef _LZMA_IN_CB\r
++    ILzmaInCallback *inCallback,\r
++    #else\r
++    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,\r
++    #endif\r
++    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);\r
++\r
++#endif\r
+diff -urN linux-2.6.23/fs/squashfs/LzmaTypes.h linux-2.6.23.sqlzma/fs/squashfs/LzmaTypes.h\r
+--- linux-2.6.23/fs/squashfs/LzmaTypes.h       1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/LzmaTypes.h        2007-10-14 13:00:30.000000000 -0400\r
+@@ -0,0 +1,45 @@\r
++/* \r
++LzmaTypes.h \r
++\r
++Types for LZMA Decoder\r
++\r
++This file written and distributed to public domain by Igor Pavlov.\r
++This file is part of LZMA SDK 4.40 (2006-05-01)\r
++*/\r
++\r
++#ifndef __LZMATYPES_H\r
++#define __LZMATYPES_H\r
++\r
++#ifndef _7ZIP_BYTE_DEFINED\r
++#define _7ZIP_BYTE_DEFINED\r
++typedef unsigned char Byte;\r
++#endif \r
++\r
++#ifndef _7ZIP_UINT16_DEFINED\r
++#define _7ZIP_UINT16_DEFINED\r
++typedef unsigned short UInt16;\r
++#endif \r
++\r
++#ifndef _7ZIP_UINT32_DEFINED\r
++#define _7ZIP_UINT32_DEFINED\r
++#ifdef _LZMA_UINT32_IS_ULONG\r
++typedef unsigned long UInt32;\r
++#else\r
++typedef unsigned int UInt32;\r
++#endif\r
++#endif \r
++\r
++/* #define _LZMA_SYSTEM_SIZE_T */\r
++/* Use system's size_t. You can use it to enable 64-bit sizes supporting */\r
++\r
++#ifndef _7ZIP_SIZET_DEFINED\r
++#define _7ZIP_SIZET_DEFINED\r
++#ifdef _LZMA_SYSTEM_SIZE_T\r
++#include <stddef.h>\r
++typedef size_t SizeT;\r
++#else\r
++typedef UInt32 SizeT;\r
++#endif\r
++#endif\r
++\r
++#endif\r
+diff -urN linux-2.6.23/fs/squashfs/Makefile linux-2.6.23.sqlzma/fs/squashfs/Makefile\r
+--- linux-2.6.23/fs/squashfs/Makefile  1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/Makefile   2007-10-14 12:56:24.000000000 -0400\r
+@@ -0,0 +1,18 @@\r
++\r
++# Copyright (C) 2006 Junjiro Okajima\r
++# Copyright (C) 2006 Tomas Matejicek, slax.org\r
++\r
++# LICENSE follows the described one in lzma.txt.\r
++\r
++# $Id: Makefile,v 1.3 2006/11/27 03:54:58 jro Exp $\r
++\r
++#\r
++# Makefile for the linux squashfs routines.\r
++#\r
++\r
++obj-$(CONFIG_SQUASHFS) += unlzma.o sqlzma.o squashfs.o\r
++unlzma-y += module.o\r
++sqlzma-y += uncomp.o\r
++squashfs-y += inode.o\r
++squashfs-y += squashfs2_0.o\r
++\r
+diff -urN linux-2.6.23/fs/squashfs/inode.c linux-2.6.23.sqlzma/fs/squashfs/inode.c\r
+--- linux-2.6.23/fs/squashfs/inode.c   1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/inode.c    2007-10-14 10:29:23.000000000 -0400\r
+@@ -0,0 +1,2430 @@\r
++/*\r
++ * Squashfs - a compressed read only filesystem for Linux\r
++ *\r
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
++ * Phillip Lougher <phillip@lougher.org.uk>\r
++ *\r
++ * This program is free software; you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License\r
++ * as published by the Free Software Foundation; either version 2,\r
++ * or (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program; if not, write to the Free Software\r
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
++ *\r
++ * inode.c\r
++ */\r
++\r
++#include <linux/squashfs_fs.h>\r
++#include <linux/module.h>\r
++#include <linux/zlib.h>\r
++#include <linux/fs.h>\r
++#include <linux/squashfs_fs_sb.h>\r
++#include <linux/squashfs_fs_i.h>\r
++#include <linux/buffer_head.h>\r
++#include <linux/vfs.h>\r
++#include <linux/vmalloc.h>\r
++#include <linux/smp_lock.h>\r
++#include <linux/sched.h>\r
++#include <linux/exportfs.h>\r
++\r
++#include "squashfs.h"\r
++#include "sqlzma.h"\r
++#include "sqmagic.h"\r
++\r
++#undef KeepPreemptive\r
++#if defined(CONFIG_PREEMPT) && !defined(UnsquashNoPreempt)\r
++#define KeepPreemptive\r
++#endif\r
++\r
++struct sqlzma {\r
++#ifdef KeepPreemptive\r
++      struct mutex mtx;\r
++#endif\r
++      unsigned char read_data[SQUASHFS_FILE_MAX_SIZE];\r
++      struct sqlzma_un un;\r
++};\r
++static DEFINE_PER_CPU(struct sqlzma *, sqlzma);\r
++\r
++#define dpri(fmt, args...) /* printk("%s:%d: " fmt, __func__, __LINE__, ##args) */\r
++#define dpri_un(un)   dpri("un{%d, {%d %p}, {%d %p}, {%d %p}}\n", \\r
++                           (un)->un_lzma, (un)->un_a[0].sz, (un)->un_a[0].buf, \\r
++                           (un)->un_a[1].sz, (un)->un_a[1].buf, \\r
++                           (un)->un_a[2].sz, (un)->un_a[2].buf)\r
++\r
++static void vfs_read_inode(struct inode *i);\r
++static struct dentry *squashfs_get_parent(struct dentry *child);\r
++static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode);\r
++static int squashfs_statfs(struct dentry *, struct kstatfs *);\r
++static int squashfs_symlink_readpage(struct file *file, struct page *page);\r
++static long long read_blocklist(struct inode *inode, int index,\r
++                              int readahead_blks, char *block_list,\r
++                              unsigned short **block_p, unsigned int *bsize);\r
++static int squashfs_readpage(struct file *file, struct page *page);\r
++static int squashfs_readpage4K(struct file *file, struct page *page);\r
++static int squashfs_readdir(struct file *, void *, filldir_t);\r
++static struct dentry *squashfs_lookup(struct inode *, struct dentry *,\r
++                              struct nameidata *);\r
++static int squashfs_remount(struct super_block *s, int *flags, char *data);\r
++static void squashfs_put_super(struct super_block *);\r
++static int squashfs_get_sb(struct file_system_type *,int, const char *, void *,\r
++                              struct vfsmount *);\r
++static struct inode *squashfs_alloc_inode(struct super_block *sb);\r
++static void squashfs_destroy_inode(struct inode *inode);\r
++static int init_inodecache(void);\r
++static void destroy_inodecache(void);\r
++\r
++static struct file_system_type squashfs_fs_type = {\r
++      .owner = THIS_MODULE,\r
++      .name = "squashfs",\r
++      .get_sb = squashfs_get_sb,\r
++      .kill_sb = kill_block_super,\r
++      .fs_flags = FS_REQUIRES_DEV\r
++};\r
++\r
++static const unsigned char squashfs_filetype_table[] = {\r
++      DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK\r
++};\r
++\r
++static struct super_operations squashfs_super_ops = {\r
++      .alloc_inode = squashfs_alloc_inode,\r
++      .destroy_inode = squashfs_destroy_inode,\r
++      .statfs = squashfs_statfs,\r
++      .put_super = squashfs_put_super,\r
++      .remount_fs = squashfs_remount\r
++};\r
++\r
++static struct super_operations squashfs_export_super_ops = {\r
++      .alloc_inode = squashfs_alloc_inode,\r
++      .destroy_inode = squashfs_destroy_inode,\r
++      .statfs = squashfs_statfs,\r
++      .put_super = squashfs_put_super,\r
++      .read_inode = vfs_read_inode\r
++};\r
++\r
++static struct export_operations squashfs_export_ops = {\r
++      .get_parent = squashfs_get_parent\r
++};\r
++\r
++SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = {\r
++      .readpage = squashfs_symlink_readpage\r
++};\r
++\r
++SQSH_EXTERN const struct address_space_operations squashfs_aops = {\r
++      .readpage = squashfs_readpage\r
++};\r
++\r
++SQSH_EXTERN const struct address_space_operations squashfs_aops_4K = {\r
++      .readpage = squashfs_readpage4K\r
++};\r
++\r
++static const struct file_operations squashfs_dir_ops = {\r
++      .read = generic_read_dir,\r
++      .readdir = squashfs_readdir\r
++};\r
++\r
++SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {\r
++      .lookup = squashfs_lookup\r
++};\r
++\r
++\r
++static struct buffer_head *get_block_length(struct super_block *s,\r
++                              int *cur_index, int *offset, int *c_byte)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      unsigned short temp;\r
++      struct buffer_head *bh;\r
++\r
++      if (!(bh = sb_bread(s, *cur_index)))\r
++              goto out;\r
++\r
++      if (msblk->devblksize - *offset == 1) {\r
++              if (msblk->swap)\r
++                      ((unsigned char *) &temp)[1] = *((unsigned char *)\r
++                              (bh->b_data + *offset));\r
++              else\r
++                      ((unsigned char *) &temp)[0] = *((unsigned char *)\r
++                              (bh->b_data + *offset));\r
++              brelse(bh);\r
++              if (!(bh = sb_bread(s, ++(*cur_index))))\r
++                      goto out;\r
++              if (msblk->swap)\r
++                      ((unsigned char *) &temp)[0] = *((unsigned char *)\r
++                              bh->b_data); \r
++              else\r
++                      ((unsigned char *) &temp)[1] = *((unsigned char *)\r
++                              bh->b_data); \r
++              *c_byte = temp;\r
++              *offset = 1;\r
++      } else {\r
++              if (msblk->swap) {\r
++                      ((unsigned char *) &temp)[1] = *((unsigned char *)\r
++                              (bh->b_data + *offset));\r
++                      ((unsigned char *) &temp)[0] = *((unsigned char *)\r
++                              (bh->b_data + *offset + 1)); \r
++              } else {\r
++                      ((unsigned char *) &temp)[0] = *((unsigned char *)\r
++                              (bh->b_data + *offset));\r
++                      ((unsigned char *) &temp)[1] = *((unsigned char *)\r
++                              (bh->b_data + *offset + 1)); \r
++              }\r
++              *c_byte = temp;\r
++              *offset += 2;\r
++      }\r
++\r
++      if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {\r
++              if (*offset == msblk->devblksize) {\r
++                      brelse(bh);\r
++                      if (!(bh = sb_bread(s, ++(*cur_index))))\r
++                              goto out;\r
++                      *offset = 0;\r
++              }\r
++              if (*((unsigned char *) (bh->b_data + *offset)) !=\r
++                                              SQUASHFS_MARKER_BYTE) {\r
++                      ERROR("Metadata block marker corrupt @ %x\n",\r
++                                              *cur_index);\r
++                      brelse(bh);\r
++                      goto out;\r
++              }\r
++              (*offset)++;\r
++      }\r
++      return bh;\r
++\r
++out:\r
++      return NULL;\r
++}\r
++\r
++\r
++SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,\r
++                      long long index, unsigned int length,\r
++                      long long *next_index, int srclength)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>\r
++                      msblk->devblksize_log2) + 2];\r
++      unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);\r
++      unsigned int cur_index = index >> msblk->devblksize_log2;\r
++      int bytes, avail_bytes, b = 0, k = 0;\r
++      unsigned int compressed;\r
++      unsigned int c_byte = length;\r
++\r
++      if (c_byte) {\r
++              bytes = msblk->devblksize - offset;\r
++              compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);\r
++              c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);\r
++\r
++              TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed\r
++                                      ? "" : "un", (unsigned int) c_byte, srclength);\r
++\r
++              if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used)\r
++                      goto read_failure;\r
++\r
++              if (!(bh[0] = sb_getblk(s, cur_index)))\r
++                      goto block_release;\r
++\r
++              for (b = 1; bytes < c_byte; b++) {\r
++                      if (!(bh[b] = sb_getblk(s, ++cur_index)))\r
++                              goto block_release;\r
++                      bytes += msblk->devblksize;\r
++              }\r
++              ll_rw_block(READ, b, bh);\r
++      } else {\r
++              if (index < 0 || (index + 2) > sblk->bytes_used)\r
++                      goto read_failure;\r
++\r
++              if (!(bh[0] = get_block_length(s, &cur_index, &offset,\r
++                                                              &c_byte)))\r
++                      goto read_failure;\r
++\r
++              bytes = msblk->devblksize - offset;\r
++              compressed = SQUASHFS_COMPRESSED(c_byte);\r
++              c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);\r
++\r
++              TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed\r
++                                      ? "" : "un", (unsigned int) c_byte);\r
++\r
++              if (c_byte > srclength || (index + c_byte) > sblk->bytes_used)\r
++                      goto read_failure;\r
++\r
++              for (b = 1; bytes < c_byte; b++) {\r
++                      if (!(bh[b] = sb_getblk(s, ++cur_index)))\r
++                              goto block_release;\r
++                      bytes += msblk->devblksize;\r
++              }\r
++              ll_rw_block(READ, b - 1, bh + 1);\r
++      }\r
++\r
++      if (compressed) {\r
++              int zlib_err = Z_STREAM_END;\r
++              int rest, start;\r
++              enum {Src, Dst};\r
++              struct sized_buf sbuf[2];\r
++              struct sqlzma *percpu;\r
++\r
++              /*\r
++              * uncompress block\r
++              */\r
++              for (k = 0; k < b; k++) {\r
++                      wait_on_buffer(bh[k]);\r
++                      if (!buffer_uptodate(bh[k]))\r
++                              goto block_release;\r
++              }\r
++\r
++              avail_bytes = 0;\r
++              for (k = 0; !avail_bytes && k < b; k++) {\r
++                      avail_bytes = msblk->devblksize - offset;\r
++                      if (c_byte < avail_bytes)\r
++                              avail_bytes = c_byte;\r
++                      if (avail_bytes)\r
++                              break;\r
++                      offset = 0;\r
++                      brelse(bh[k]);\r
++              }\r
++              bytes = 0;\r
++              if (!avail_bytes)\r
++                      goto block_release; // nothing to be process\r
++\r
++              start = k;\r
++              /* it disables preemption */\r
++              percpu = get_cpu_var(sqlzma);\r
++#ifdef KeepPreemptive\r
++              put_cpu_var(sqlzma);\r
++              mutex_lock(&percpu->mtx);\r
++#endif\r
++\r
++              for (; k < b; k++) {\r
++                      memcpy(percpu->read_data + bytes, bh[k]->b_data + offset,\r
++                             avail_bytes);\r
++                      bytes += avail_bytes;\r
++                      offset = 0;\r
++                      brelse(bh[k]);\r
++                      avail_bytes = msblk->devblksize - offset;\r
++                      rest = c_byte - bytes;\r
++                      if (rest < avail_bytes)\r
++                              avail_bytes = rest;\r
++              }\r
++\r
++              sbuf[Src].buf = percpu->read_data;\r
++              sbuf[Src].sz = bytes;\r
++              sbuf[Dst].buf = buffer;\r
++              sbuf[Dst].sz = srclength;\r
++              dpri_un(&percpu->un);\r
++              dpri("src %d %p, dst %d %p\n", sbuf[Src].sz, sbuf[Src].buf,\r
++                   sbuf[Dst].sz, sbuf[Dst].buf);\r
++              zlib_err = sqlzma_un(&percpu->un, sbuf + Src, sbuf + Dst);\r
++              bytes = percpu->un.un_reslen;\r
++\r
++#ifdef KeepPreemptive\r
++              mutex_unlock(&percpu->mtx);\r
++#else\r
++              put_cpu_var(sqlzma);\r
++#endif\r
++              if (unlikely(zlib_err)) {\r
++                      dpri("zlib_err %d\n", zlib_err);\r
++                      goto release_mutex;\r
++              }\r
++      } else {\r
++              int i;\r
++\r
++              for(i = 0; i < b; i++) {\r
++                      wait_on_buffer(bh[i]);\r
++                      if(!buffer_uptodate(bh[i]))\r
++                              goto block_release;\r
++              }\r
++\r
++              for (bytes = 0; k < b; k++) {\r
++                      avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?\r
++                                      msblk->devblksize - offset :\r
++                                      c_byte - bytes;\r
++                      memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes);\r
++                      bytes += avail_bytes;\r
++                      offset = 0;\r
++                      brelse(bh[k]);\r
++              }\r
++      }\r
++\r
++      if (next_index)\r
++              *next_index = index + c_byte + (length ? 0 :\r
++                              (SQUASHFS_CHECK_DATA(msblk->sblk.flags)\r
++                               ? 3 : 2));\r
++      return bytes;\r
++\r
++release_mutex:\r
++      //mutex_unlock(&msblk->read_data_mutex);\r
++\r
++block_release:\r
++      for (; k < b; k++)\r
++              brelse(bh[k]);\r
++\r
++read_failure:\r
++      ERROR("sb_bread failed reading block 0x%x\n", cur_index);\r
++      return 0;\r
++}\r
++\r
++\r
++SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,\r
++                              long long block, unsigned int offset,\r
++                              int length, long long *next_block,\r
++                              unsigned int *next_offset)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      int n, i, bytes, return_length = length;\r
++      long long next_index;\r
++\r
++      TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);\r
++\r
++      while ( 1 ) {\r
++              for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) \r
++                      if (msblk->block_cache[i].block == block)\r
++                              break; \r
++              \r
++              mutex_lock(&msblk->block_cache_mutex);\r
++\r
++              if (i == SQUASHFS_CACHED_BLKS) {\r
++                      /* read inode header block */\r
++                      for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;\r
++                                      n ; n --, i = (i + 1) %\r
++                                      SQUASHFS_CACHED_BLKS)\r
++                              if (msblk->block_cache[i].block !=\r
++                                                      SQUASHFS_USED_BLK)\r
++                                      break;\r
++\r
++                      if (n == 0) {\r
++                              wait_queue_t wait;\r
++\r
++                              init_waitqueue_entry(&wait, current);\r
++                              add_wait_queue(&msblk->waitq, &wait);\r
++                              set_current_state(TASK_UNINTERRUPTIBLE);\r
++                              mutex_unlock(&msblk->block_cache_mutex);\r
++                              schedule();\r
++                              set_current_state(TASK_RUNNING);\r
++                              remove_wait_queue(&msblk->waitq, &wait);\r
++                              continue;\r
++                      }\r
++                      msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;\r
++\r
++                      if (msblk->block_cache[i].block ==\r
++                                                      SQUASHFS_INVALID_BLK) {\r
++                              if (!(msblk->block_cache[i].data =\r
++                                              kmalloc(SQUASHFS_METADATA_SIZE,\r
++                                              GFP_KERNEL))) {\r
++                                      ERROR("Failed to allocate cache"\r
++                                                      "block\n");\r
++                                      mutex_unlock(&msblk->block_cache_mutex);\r
++                                      goto out;\r
++                              }\r
++                      }\r
++      \r
++                      msblk->block_cache[i].block = SQUASHFS_USED_BLK;\r
++                      mutex_unlock(&msblk->block_cache_mutex);\r
++\r
++                      msblk->block_cache[i].length = squashfs_read_data(s,\r
++                              msblk->block_cache[i].data, block, 0, &next_index, SQUASHFS_METADATA_SIZE);\r
++                      if (msblk->block_cache[i].length == 0) {\r
++                              ERROR("Unable to read cache block [%llx:%x]\n",\r
++                                              block, offset);\r
++                              mutex_lock(&msblk->block_cache_mutex);\r
++                              msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;\r
++                              kfree(msblk->block_cache[i].data);\r
++                              wake_up(&msblk->waitq);\r
++                              mutex_unlock(&msblk->block_cache_mutex);\r
++                              goto out;\r
++                      }\r
++\r
++                      mutex_lock(&msblk->block_cache_mutex);\r
++                      wake_up(&msblk->waitq);\r
++                      msblk->block_cache[i].block = block;\r
++                      msblk->block_cache[i].next_index = next_index;\r
++                      TRACE("Read cache block [%llx:%x]\n", block, offset);\r
++              }\r
++\r
++              if (msblk->block_cache[i].block != block) {\r
++                      mutex_unlock(&msblk->block_cache_mutex);\r
++                      continue;\r
++              }\r
++\r
++              bytes = msblk->block_cache[i].length - offset;\r
++\r
++              if (bytes < 1) {\r
++                      mutex_unlock(&msblk->block_cache_mutex);\r
++                      goto out;\r
++              } else if (bytes >= length) {\r
++                      if (buffer)\r
++                              memcpy(buffer, msblk->block_cache[i].data +\r
++                                              offset, length);\r
++                      if (msblk->block_cache[i].length - offset == length) {\r
++                              *next_block = msblk->block_cache[i].next_index;\r
++                              *next_offset = 0;\r
++                      } else {\r
++                              *next_block = block;\r
++                              *next_offset = offset + length;\r
++                      }\r
++                      mutex_unlock(&msblk->block_cache_mutex);\r
++                      goto finish;\r
++              } else {\r
++                      if (buffer) {\r
++                              memcpy(buffer, msblk->block_cache[i].data +\r
++                                              offset, bytes);\r
++                              buffer += bytes;\r
++                      }\r
++                      block = msblk->block_cache[i].next_index;\r
++                      mutex_unlock(&msblk->block_cache_mutex);\r
++                      length -= bytes;\r
++                      offset = 0;\r
++              }\r
++      }\r
++\r
++finish:\r
++      return return_length;\r
++out:\r
++      return 0;\r
++}\r
++\r
++\r
++static int get_fragment_location(struct super_block *s, unsigned int fragment,\r
++                              long long *fragment_start_block,\r
++                              unsigned int *fragment_size)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      long long start_block =\r
++              msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];\r
++      int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);\r
++      struct squashfs_fragment_entry fragment_entry;\r
++\r
++      if (msblk->swap) {\r
++              struct squashfs_fragment_entry sfragment_entry;\r
++\r
++              if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,\r
++                                      start_block, offset,\r
++                                      sizeof(sfragment_entry), &start_block,\r
++                                      &offset))\r
++                      goto out;\r
++              SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);\r
++      } else\r
++              if (!squashfs_get_cached_block(s, (char *) &fragment_entry,\r
++                                      start_block, offset,\r
++                                      sizeof(fragment_entry), &start_block,\r
++                                      &offset))\r
++                      goto out;\r
++\r
++      *fragment_start_block = fragment_entry.start_block;\r
++      *fragment_size = fragment_entry.size;\r
++\r
++      return 1;\r
++\r
++out:\r
++      return 0;\r
++}\r
++\r
++\r
++SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct\r
++                                      squashfs_fragment_cache *fragment)\r
++{\r
++      mutex_lock(&msblk->fragment_mutex);\r
++      fragment->locked --;\r
++      wake_up(&msblk->fragment_wait_queue);\r
++      mutex_unlock(&msblk->fragment_mutex);\r
++}\r
++\r
++\r
++SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block\r
++                                      *s, long long start_block,\r
++                                      int length)\r
++{\r
++      int i, n;\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++\r
++      while ( 1 ) {\r
++              mutex_lock(&msblk->fragment_mutex);\r
++\r
++              for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&\r
++                              msblk->fragment[i].block != start_block; i++);\r
++\r
++              if (i == SQUASHFS_CACHED_FRAGMENTS) {\r
++                      for (i = msblk->next_fragment, n =\r
++                              SQUASHFS_CACHED_FRAGMENTS; n &&\r
++                              msblk->fragment[i].locked; n--, i = (i + 1) %\r
++                              SQUASHFS_CACHED_FRAGMENTS);\r
++\r
++                      if (n == 0) {\r
++                              wait_queue_t wait;\r
++\r
++                              init_waitqueue_entry(&wait, current);\r
++                              add_wait_queue(&msblk->fragment_wait_queue,\r
++                                                                      &wait);\r
++                              set_current_state(TASK_UNINTERRUPTIBLE);\r
++                              mutex_unlock(&msblk->fragment_mutex);\r
++                              schedule();\r
++                              set_current_state(TASK_RUNNING);\r
++                              remove_wait_queue(&msblk->fragment_wait_queue,\r
++                                                                      &wait);\r
++                              continue;\r
++                      }\r
++                      msblk->next_fragment = (msblk->next_fragment + 1) %\r
++                              SQUASHFS_CACHED_FRAGMENTS;\r
++                      \r
++                      if (msblk->fragment[i].data == NULL)\r
++                              if (!(msblk->fragment[i].data = SQUASHFS_ALLOC\r
++                                              (SQUASHFS_FILE_MAX_SIZE))) {\r
++                                      ERROR("Failed to allocate fragment "\r
++                                                      "cache block\n");\r
++                                      mutex_unlock(&msblk->fragment_mutex);\r
++                                      goto out;\r
++                              }\r
++\r
++                      msblk->fragment[i].block = SQUASHFS_INVALID_BLK;\r
++                      msblk->fragment[i].locked = 1;\r
++                      mutex_unlock(&msblk->fragment_mutex);\r
++\r
++                      if (!(msblk->fragment[i].length = squashfs_read_data(s,\r
++                                              msblk->fragment[i].data,\r
++                                              start_block, length, NULL, sblk->block_size))) {\r
++                              ERROR("Unable to read fragment cache block "\r
++                                                      "[%llx]\n", start_block);\r
++                              msblk->fragment[i].locked = 0;\r
++                              smp_mb();\r
++                              goto out;\r
++                      }\r
++\r
++                      mutex_lock(&msblk->fragment_mutex);\r
++                      msblk->fragment[i].block = start_block;\r
++                      TRACE("New fragment %d, start block %lld, locked %d\n",\r
++                                              i, msblk->fragment[i].block,\r
++                                              msblk->fragment[i].locked);\r
++                      mutex_unlock(&msblk->fragment_mutex);\r
++                      break;\r
++              }\r
++\r
++              msblk->fragment[i].locked++;\r
++              mutex_unlock(&msblk->fragment_mutex);\r
++              TRACE("Got fragment %d, start block %lld, locked %d\n", i,\r
++                                              msblk->fragment[i].block,\r
++                                              msblk->fragment[i].locked);\r
++              break;\r
++      }\r
++\r
++      return &msblk->fragment[i];\r
++\r
++out:\r
++      return NULL;\r
++}\r
++\r
++\r
++static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,\r
++              struct squashfs_base_inode_header *inodeb)\r
++{\r
++      i->i_ino = inodeb->inode_number;\r
++      i->i_mtime.tv_sec = inodeb->mtime;\r
++      i->i_atime.tv_sec = inodeb->mtime;\r
++      i->i_ctime.tv_sec = inodeb->mtime;\r
++      i->i_uid = msblk->uid[inodeb->uid];\r
++      i->i_mode = inodeb->mode;\r
++      i->i_size = 0;\r
++      if (inodeb->guid == SQUASHFS_GUIDS)\r
++              i->i_gid = i->i_uid;\r
++      else\r
++              i->i_gid = msblk->guid[inodeb->guid];\r
++}\r
++\r
++\r
++static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)];\r
++      int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1);\r
++      squashfs_inode_t inode;\r
++\r
++      TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino);\r
++\r
++      if (msblk->swap) {\r
++              squashfs_inode_t sinode;\r
++\r
++              if (!squashfs_get_cached_block(s, (char *) &sinode, start, offset,\r
++                                      sizeof(sinode), &start, &offset))\r
++                      goto out;\r
++              SQUASHFS_SWAP_INODE_T((&inode), &sinode);\r
++      } else if (!squashfs_get_cached_block(s, (char *) &inode, start, offset,\r
++                                      sizeof(inode), &start, &offset))\r
++                      goto out;\r
++\r
++      TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode);\r
++\r
++      return inode;\r
++\r
++out:\r
++      return SQUASHFS_INVALID_BLK;\r
++}\r
++      \r
++\r
++static void vfs_read_inode(struct inode *i)\r
++{\r
++      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
++      squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino);\r
++\r
++      TRACE("Entered vfs_read_inode\n");\r
++\r
++      if(inode != SQUASHFS_INVALID_BLK)\r
++              (msblk->read_inode)(i, inode);\r
++}\r
++\r
++\r
++static struct dentry *squashfs_get_parent(struct dentry *child)\r
++{\r
++      struct inode *i = child->d_inode;\r
++      struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode);\r
++      struct dentry *rv;\r
++\r
++      TRACE("Entered squashfs_get_parent\n");\r
++\r
++      if(parent == NULL) {\r
++              rv = ERR_PTR(-EACCES);\r
++              goto out;\r
++      }\r
++\r
++      rv = d_alloc_anon(parent);\r
++      if(rv == NULL)\r
++              rv = ERR_PTR(-ENOMEM);\r
++\r
++out:\r
++      return rv;\r
++}\r
++\r
++      \r
++SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct inode *i = iget_locked(s, inode_number);\r
++\r
++      TRACE("Entered squashfs_iget\n");\r
++\r
++      if(i && (i->i_state & I_NEW)) {\r
++              (msblk->read_inode)(i, inode);\r
++              unlock_new_inode(i);\r
++      }\r
++\r
++      return i;\r
++}\r
++\r
++\r
++static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode)\r
++{\r
++      struct super_block *s = i->i_sb;\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      long long block = SQUASHFS_INODE_BLK(inode) +\r
++              sblk->inode_table_start;\r
++      unsigned int offset = SQUASHFS_INODE_OFFSET(inode);\r
++      long long next_block;\r
++      unsigned int next_offset;\r
++      union squashfs_inode_header id, sid;\r
++      struct squashfs_base_inode_header *inodeb = &id.base,\r
++                                        *sinodeb = &sid.base;\r
++\r
++      TRACE("Entered squashfs_read_inode\n");\r
++\r
++      if (msblk->swap) {\r
++              if (!squashfs_get_cached_block(s, (char *) sinodeb, block,\r
++                                      offset, sizeof(*sinodeb), &next_block,\r
++                                      &next_offset))\r
++                      goto failed_read;\r
++              SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,\r
++                                      sizeof(*sinodeb));\r
++      } else\r
++              if (!squashfs_get_cached_block(s, (char *) inodeb, block,\r
++                                      offset, sizeof(*inodeb), &next_block,\r
++                                      &next_offset))\r
++                      goto failed_read;\r
++\r
++      squashfs_new_inode(msblk, i, inodeb);\r
++\r
++      switch(inodeb->inode_type) {\r
++              case SQUASHFS_FILE_TYPE: {\r
++                      unsigned int frag_size;\r
++                      long long frag_blk;\r
++                      struct squashfs_reg_inode_header *inodep = &id.reg;\r
++                      struct squashfs_reg_inode_header *sinodep = &sid.reg;\r
++                              \r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      frag_blk = SQUASHFS_INVALID_BLK;\r
++                      if (inodep->fragment != SQUASHFS_INVALID_FRAG &&\r
++                                      !get_fragment_location(s,\r
++                                      inodep->fragment, &frag_blk, &frag_size))\r
++                              goto failed_read;\r
++                              \r
++                      i->i_nlink = 1;\r
++                      i->i_size = inodep->file_size;\r
++                      i->i_fop = &generic_ro_fops;\r
++                      i->i_mode |= S_IFREG;\r
++                      i->i_blocks = ((i->i_size - 1) >> 9) + 1;\r
++                      SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;\r
++                      SQUASHFS_I(i)->u.s1.fragment_size = frag_size;\r
++                      SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->u.s1.block_list_start = next_block;\r
++                      SQUASHFS_I(i)->offset = next_offset;\r
++                      if (sblk->block_size > 4096)\r
++                              i->i_data.a_ops = &squashfs_aops;\r
++                      else\r
++                              i->i_data.a_ops = &squashfs_aops_4K;\r
++\r
++                      TRACE("File inode %x:%x, start_block %llx, "\r
++                                      "block_list_start %llx, offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->start_block, next_block,\r
++                                      next_offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_LREG_TYPE: {\r
++                      unsigned int frag_size;\r
++                      long long frag_blk;\r
++                      struct squashfs_lreg_inode_header *inodep = &id.lreg;\r
++                      struct squashfs_lreg_inode_header *sinodep = &sid.lreg;\r
++                              \r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      frag_blk = SQUASHFS_INVALID_BLK;\r
++                      if (inodep->fragment != SQUASHFS_INVALID_FRAG &&\r
++                                      !get_fragment_location(s,\r
++                                      inodep->fragment, &frag_blk, &frag_size))\r
++                              goto failed_read;\r
++                              \r
++                      i->i_nlink = inodep->nlink;\r
++                      i->i_size = inodep->file_size;\r
++                      i->i_fop = &generic_ro_fops;\r
++                      i->i_mode |= S_IFREG;\r
++                      i->i_blocks = ((i->i_size - 1) >> 9) + 1;\r
++                      SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;\r
++                      SQUASHFS_I(i)->u.s1.fragment_size = frag_size;\r
++                      SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->u.s1.block_list_start = next_block;\r
++                      SQUASHFS_I(i)->offset = next_offset;\r
++                      if (sblk->block_size > 4096)\r
++                              i->i_data.a_ops = &squashfs_aops;\r
++                      else\r
++                              i->i_data.a_ops = &squashfs_aops_4K;\r
++\r
++                      TRACE("File inode %x:%x, start_block %llx, "\r
++                                      "block_list_start %llx, offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->start_block, next_block,\r
++                                      next_offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_DIR_TYPE: {\r
++                      struct squashfs_dir_inode_header *inodep = &id.dir;\r
++                      struct squashfs_dir_inode_header *sinodep = &sid.dir;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_nlink = inodep->nlink;\r
++                      i->i_size = inodep->file_size;\r
++                      i->i_op = &squashfs_dir_inode_ops;\r
++                      i->i_fop = &squashfs_dir_ops;\r
++                      i->i_mode |= S_IFDIR;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->offset = inodep->offset;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_count = 0;\r
++                      SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;\r
++\r
++                      TRACE("Directory inode %x:%x, start_block %x, offset "\r
++                                      "%x\n", SQUASHFS_INODE_BLK(inode),\r
++                                      offset, inodep->start_block,\r
++                                      inodep->offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_LDIR_TYPE: {\r
++                      struct squashfs_ldir_inode_header *inodep = &id.ldir;\r
++                      struct squashfs_ldir_inode_header *sinodep = &sid.ldir;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,\r
++                                              sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_nlink = inodep->nlink;\r
++                      i->i_size = inodep->file_size;\r
++                      i->i_op = &squashfs_dir_inode_ops;\r
++                      i->i_fop = &squashfs_dir_ops;\r
++                      i->i_mode |= S_IFDIR;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->offset = inodep->offset;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_start = next_block;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_offset =\r
++                                                              next_offset;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_count =\r
++                                                              inodep->i_count;\r
++                      SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;\r
++\r
++                      TRACE("Long directory inode %x:%x, start_block %x, "\r
++                                      "offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->start_block, inodep->offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_SYMLINK_TYPE: {\r
++                      struct squashfs_symlink_inode_header *inodep =\r
++                                                              &id.symlink;\r
++                      struct squashfs_symlink_inode_header *sinodep =\r
++                                                              &sid.symlink;\r
++      \r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,\r
++                                                              sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_nlink = inodep->nlink;\r
++                      i->i_size = inodep->symlink_size;\r
++                      i->i_op = &page_symlink_inode_operations;\r
++                      i->i_data.a_ops = &squashfs_symlink_aops;\r
++                      i->i_mode |= S_IFLNK;\r
++                      SQUASHFS_I(i)->start_block = next_block;\r
++                      SQUASHFS_I(i)->offset = next_offset;\r
++\r
++                      TRACE("Symbolic link inode %x:%x, start_block %llx, "\r
++                                      "offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      next_block, next_offset);\r
++                      break;\r
++               }\r
++               case SQUASHFS_BLKDEV_TYPE:\r
++               case SQUASHFS_CHRDEV_TYPE: {\r
++                      struct squashfs_dev_inode_header *inodep = &id.dev;\r
++                      struct squashfs_dev_inode_header *sinodep = &sid.dev;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);\r
++                      } else  \r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_nlink = inodep->nlink;\r
++                      i->i_mode |= (inodeb->inode_type ==\r
++                                      SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :\r
++                                      S_IFBLK;\r
++                      init_special_inode(i, i->i_mode,\r
++                                      old_decode_dev(inodep->rdev));\r
++\r
++                      TRACE("Device inode %x:%x, rdev %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->rdev);\r
++                      break;\r
++               }\r
++               case SQUASHFS_FIFO_TYPE:\r
++               case SQUASHFS_SOCKET_TYPE: {\r
++                      struct squashfs_ipc_inode_header *inodep = &id.ipc;\r
++                      struct squashfs_ipc_inode_header *sinodep = &sid.ipc;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);\r
++                      } else  \r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_nlink = inodep->nlink;\r
++                      i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)\r
++                                                      ? S_IFIFO : S_IFSOCK;\r
++                      init_special_inode(i, i->i_mode, 0);\r
++                      break;\r
++               }\r
++               default:\r
++                      ERROR("Unknown inode type %d in squashfs_iget!\n",\r
++                                      inodeb->inode_type);\r
++                      goto failed_read1;\r
++      }\r
++      \r
++      return 1;\r
++\r
++failed_read:\r
++      ERROR("Unable to read inode [%llx:%x]\n", block, offset);\r
++\r
++failed_read1:\r
++      make_bad_inode(i);\r
++      return 0;\r
++}\r
++\r
++\r
++static int read_inode_lookup_table(struct super_block *s)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes);\r
++\r
++      TRACE("In read_inode_lookup_table, length %d\n", length);\r
++\r
++      /* Allocate inode lookup table */\r
++      if (!(msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate inode lookup table\n");\r
++              return 0;\r
++      }\r
++   \r
++      if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table,\r
++                      sblk->lookup_table_start, length |\r
++                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {\r
++              ERROR("unable to read inode lookup table\n");\r
++              return 0;\r
++      }\r
++\r
++      if (msblk->swap) {\r
++              int i;\r
++              long long block;\r
++\r
++              for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) {\r
++                      SQUASHFS_SWAP_LOOKUP_BLOCKS((&block),\r
++                                              &msblk->inode_lookup_table[i], 1);\r
++                      msblk->inode_lookup_table[i] = block;\r
++              }\r
++      }\r
++\r
++      return 1;\r
++}\r
++\r
++\r
++static int read_fragment_index_table(struct super_block *s)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments);\r
++\r
++      if(length == 0)\r
++              return 1;\r
++\r
++      /* Allocate fragment index table */\r
++      if (!(msblk->fragment_index = kmalloc(length, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate fragment index table\n");\r
++              return 0;\r
++      }\r
++   \r
++      if (!squashfs_read_data(s, (char *) msblk->fragment_index,\r
++                      sblk->fragment_table_start, length |\r
++                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {\r
++              ERROR("unable to read fragment index table\n");\r
++              return 0;\r
++      }\r
++\r
++      if (msblk->swap) {\r
++              int i;\r
++              long long fragment;\r
++\r
++              for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) {\r
++                      SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),\r
++                                              &msblk->fragment_index[i], 1);\r
++                      msblk->fragment_index[i] = fragment;\r
++              }\r
++      }\r
++\r
++      return 1;\r
++}\r
++\r
++\r
++static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)\r
++{\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++\r
++      msblk->read_inode = squashfs_read_inode;\r
++      msblk->read_blocklist = read_blocklist;\r
++      msblk->read_fragment_index_table = read_fragment_index_table;\r
++\r
++      if (sblk->s_major == 1) {\r
++              if (!squashfs_1_0_supported(msblk)) {\r
++                      SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "\r
++                              "are unsupported\n");\r
++                      SERROR("Please recompile with "\r
++                              "Squashfs 1.0 support enabled\n");\r
++                      return 0;\r
++              }\r
++      } else if (sblk->s_major == 2) {\r
++              if (!squashfs_2_0_supported(msblk)) {\r
++                      SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "\r
++                              "are unsupported\n");\r
++                      SERROR("Please recompile with "\r
++                              "Squashfs 2.0 support enabled\n");\r
++                      return 0;\r
++              }\r
++      } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >\r
++                      SQUASHFS_MINOR) {\r
++              SERROR("Major/Minor mismatch, trying to mount newer %d.%d "\r
++                              "filesystem\n", sblk->s_major, sblk->s_minor);\r
++              SERROR("Please update your kernel\n");\r
++              return 0;\r
++      }\r
++\r
++      return 1;\r
++}\r
++\r
++\r
++static int squashfs_fill_super(struct super_block *s, void *data, int silent)\r
++{\r
++      struct squashfs_sb_info *msblk;\r
++      struct squashfs_super_block *sblk;\r
++      int i, err;\r
++      char b[BDEVNAME_SIZE];\r
++      struct inode *root;\r
++      void *label;\r
++\r
++      TRACE("Entered squashfs_read_superblock\n");\r
++\r
++      err = -ENOMEM;\r
++      if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),\r
++                                              GFP_KERNEL))) {\r
++              ERROR("Failed to allocate superblock\n");\r
++              goto failure;\r
++      }\r
++      label = &&out_fsinfo;\r
++      memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));\r
++      msblk = s->s_fs_info;\r
++      sblk = &msblk->sblk;\r
++      \r
++      msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);\r
++      msblk->devblksize_log2 = ffz(~msblk->devblksize);\r
++\r
++      //mutex_init(&msblk->read_data_mutex);\r
++      mutex_init(&msblk->read_page_mutex);\r
++      mutex_init(&msblk->block_cache_mutex);\r
++      mutex_init(&msblk->fragment_mutex);\r
++      mutex_init(&msblk->meta_index_mutex);\r
++      \r
++      init_waitqueue_head(&msblk->waitq);\r
++      init_waitqueue_head(&msblk->fragment_wait_queue);\r
++\r
++      err = -EINVAL;\r
++      sblk->bytes_used = sizeof(struct squashfs_super_block);\r
++      if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,\r
++                                      sizeof(struct squashfs_super_block) |\r
++                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) {\r
++              SERROR("unable to read superblock\n");\r
++              goto *label;\r
++      }\r
++\r
++      /* Check it is a SQUASHFS superblock */\r
++      s->s_magic = sblk->s_magic;\r
++      msblk->swap = 0;\r
++      dpri("magic 0x%x\n", sblk->s_magic);\r
++      switch (sblk->s_magic) {\r
++              struct squashfs_super_block ssblk;\r
++\r
++      case SQUASHFS_MAGIC_SWAP:\r
++              /*FALLTHROUGH*/\r
++      case SQUASHFS_MAGIC_LZMA_SWAP:\r
++              WARNING("Mounting a different endian SQUASHFS "\r
++                      "filesystem on %s\n", bdevname(s->s_bdev, b));\r
++\r
++              SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);\r
++              memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));\r
++              msblk->swap = 1;\r
++              /*FALLTHROUGH*/\r
++      case SQUASHFS_MAGIC:\r
++      case SQUASHFS_MAGIC_LZMA:\r
++              break;\r
++      default:\r
++              SERROR("Can't find a SQUASHFS superblock on %s\n",\r
++                     bdevname(s->s_bdev, b));\r
++              goto *label;\r
++      }\r
++\r
++      {\r
++              struct sqlzma *p;\r
++              dpri("block_size %d\n", sblk->block_size);\r
++              BUG_ON(sblk->block_size > sizeof(p->read_data));\r
++      }\r
++\r
++      /* Check the MAJOR & MINOR versions */\r
++      err = -EINVAL;\r
++      if(!supported_squashfs_filesystem(msblk, silent))\r
++              goto *label;\r
++\r
++      /* Check the filesystem does not extend beyond the end of the\r
++         block device */\r
++      if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode))\r
++              goto *label;\r
++\r
++      /* Check the root inode for sanity */\r
++      if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE)\r
++              goto *label;\r
++\r
++      TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));\r
++      TRACE("Inodes are %scompressed\n",\r
++                                      SQUASHFS_UNCOMPRESSED_INODES\r
++                                      (sblk->flags) ? "un" : "");\r
++      TRACE("Data is %scompressed\n",\r
++                                      SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)\r
++                                      ? "un" : "");\r
++      TRACE("Check data is %s present in the filesystem\n",\r
++                                      SQUASHFS_CHECK_DATA(sblk->flags) ?\r
++                                      "" : "not");\r
++      TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);\r
++      TRACE("Block size %d\n", sblk->block_size);\r
++      TRACE("Number of inodes %d\n", sblk->inodes);\r
++      if (sblk->s_major > 1)\r
++              TRACE("Number of fragments %d\n", sblk->fragments);\r
++      TRACE("Number of uids %d\n", sblk->no_uids);\r
++      TRACE("Number of gids %d\n", sblk->no_guids);\r
++      TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);\r
++      TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);\r
++      if (sblk->s_major > 1)\r
++              TRACE("sblk->fragment_table_start %llx\n",\r
++                                      sblk->fragment_table_start);\r
++      TRACE("sblk->uid_start %llx\n", sblk->uid_start);\r
++\r
++      s->s_flags |= MS_RDONLY;\r
++      s->s_op = &squashfs_super_ops;\r
++\r
++      /* Init inode_table block pointer array */\r
++      err = -ENOMEM;\r
++      if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *\r
++                                      SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate block cache\n");\r
++              goto *label;\r
++      }\r
++      label = &&out_block_cache;\r
++\r
++      for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)\r
++              msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;\r
++\r
++      msblk->next_cache = 0;\r
++\r
++      /* Allocate read_page block */\r
++      if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate read_page block\n");\r
++              goto *label;\r
++      }\r
++      label = &&out_read_page;\r
++\r
++      /* Allocate uid and gid tables */\r
++      if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *\r
++                                      sizeof(unsigned int), GFP_KERNEL))) {\r
++              ERROR("Failed to allocate uid/gid table\n");\r
++              goto *label;\r
++      }\r
++      label = &&out_uid;\r
++      msblk->guid = msblk->uid + sblk->no_uids;\r
++   \r
++      dpri("swap %d\n", msblk->swap);\r
++      err = -EINVAL;\r
++      if (msblk->swap) {\r
++              unsigned int suid[sblk->no_uids + sblk->no_guids];\r
++\r
++              if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,\r
++                                      ((sblk->no_uids + sblk->no_guids) *\r
++                                       sizeof(unsigned int)) |\r
++                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {\r
++                      ERROR("unable to read uid/gid table\n");\r
++                      goto *label;\r
++              }\r
++\r
++              SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +\r
++                      sblk->no_guids), (sizeof(unsigned int) * 8));\r
++      } else\r
++              if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,\r
++                                      ((sblk->no_uids + sblk->no_guids) *\r
++                                       sizeof(unsigned int)) |\r
++                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {\r
++                      ERROR("unable to read uid/gid table\n");\r
++                      goto *label;\r
++              }\r
++\r
++\r
++      if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))\r
++              goto allocate_root;\r
++\r
++      err = -ENOMEM;\r
++      if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *\r
++                              SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate fragment block cache\n");\r
++              goto *label;\r
++      }\r
++      label = &&out_fragment;\r
++\r
++      for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {\r
++              msblk->fragment[i].locked = 0;\r
++              msblk->fragment[i].block = SQUASHFS_INVALID_BLK;\r
++              msblk->fragment[i].data = NULL;\r
++      }\r
++\r
++      msblk->next_fragment = 0;\r
++\r
++      /* Allocate and read fragment index table */\r
++      if (msblk->read_fragment_index_table(s) == 0)\r
++              goto *label;\r
++\r
++      if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK)\r
++              goto allocate_root;\r
++\r
++      /* Allocate and read inode lookup table */\r
++      if (read_inode_lookup_table(s) == 0)\r
++              goto failed_mount;\r
++\r
++      s->s_op = &squashfs_export_super_ops;\r
++      s->s_export_op = &squashfs_export_ops;\r
++\r
++allocate_root:\r
++      dpri("alloate_root\n");\r
++      root = new_inode(s);\r
++      if ((msblk->read_inode)(root, sblk->root_inode) == 0) {\r
++              iput(root);\r
++              goto failed_mount;\r
++      }\r
++      insert_inode_hash(root);\r
++\r
++      if ((s->s_root = d_alloc_root(root)) == NULL) {\r
++              ERROR("Root inode create failed\n");\r
++              iput(root);\r
++              goto failed_mount;\r
++      }\r
++\r
++      TRACE("Leaving squashfs_read_super\n");\r
++      return 0;\r
++\r
++failed_mount:\r
++      kfree(msblk->inode_lookup_table);\r
++      kfree(msblk->fragment_index);\r
++      kfree(msblk->fragment_index_2);\r
++ out_fragment:\r
++      kfree(msblk->fragment);\r
++ out_uid:\r
++      kfree(msblk->uid);\r
++ out_read_page:\r
++      kfree(msblk->read_page);\r
++ out_block_cache:\r
++      kfree(msblk->block_cache);\r
++ out_fsinfo:\r
++      kfree(s->s_fs_info);\r
++      s->s_fs_info = NULL;\r
++ failure:\r
++      return err;\r
++}\r
++\r
++\r
++static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)\r
++{\r
++      struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++\r
++      TRACE("Entered squashfs_statfs\n");\r
++\r
++      buf->f_type = sblk->s_magic;\r
++      buf->f_bsize = sblk->block_size;\r
++      buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;\r
++      buf->f_bfree = buf->f_bavail = 0;\r
++      buf->f_files = sblk->inodes;\r
++      buf->f_ffree = 0;\r
++      buf->f_namelen = SQUASHFS_NAME_LEN;\r
++\r
++      return 0;\r
++}\r
++\r
++\r
++static int squashfs_symlink_readpage(struct file *file, struct page *page)\r
++{\r
++      struct inode *inode = page->mapping->host;\r
++      int index = page->index << PAGE_CACHE_SHIFT, length, bytes;\r
++      long long block = SQUASHFS_I(inode)->start_block;\r
++      int offset = SQUASHFS_I(inode)->offset;\r
++      void *pageaddr = kmap(page);\r
++\r
++      TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "\r
++                              "%llx, offset %x\n", page->index,\r
++                              SQUASHFS_I(inode)->start_block,\r
++                              SQUASHFS_I(inode)->offset);\r
++\r
++      for (length = 0; length < index; length += bytes) {\r
++              if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,\r
++                              block, offset, PAGE_CACHE_SIZE, &block,\r
++                              &offset))) {\r
++                      ERROR("Unable to read symbolic link [%llx:%x]\n", block,\r
++                                      offset);\r
++                      goto skip_read;\r
++              }\r
++      }\r
++\r
++      if (length != index) {\r
++              ERROR("(squashfs_symlink_readpage) length != index\n");\r
++              bytes = 0;\r
++              goto skip_read;\r
++      }\r
++\r
++      bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :\r
++                                      i_size_read(inode) - length;\r
++\r
++      if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,\r
++                                      offset, bytes, &block, &offset)))\r
++              ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);\r
++\r
++skip_read:\r
++      memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);\r
++      kunmap(page);\r
++      flush_dcache_page(page);\r
++      SetPageUptodate(page);\r
++      unlock_page(page);\r
++\r
++      return 0;\r
++}\r
++\r
++\r
++struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)\r
++{\r
++      struct meta_index *meta = NULL;\r
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
++      int i;\r
++\r
++      mutex_lock(&msblk->meta_index_mutex);\r
++\r
++      TRACE("locate_meta_index: index %d, offset %d\n", index, offset);\r
++\r
++      if(msblk->meta_index == NULL)\r
++              goto not_allocated;\r
++\r
++      for (i = 0; i < SQUASHFS_META_NUMBER; i ++)\r
++              if (msblk->meta_index[i].inode_number == inode->i_ino &&\r
++                              msblk->meta_index[i].offset >= offset &&\r
++                              msblk->meta_index[i].offset <= index &&\r
++                              msblk->meta_index[i].locked == 0) {\r
++                      TRACE("locate_meta_index: entry %d, offset %d\n", i,\r
++                                      msblk->meta_index[i].offset);\r
++                      meta = &msblk->meta_index[i];\r
++                      offset = meta->offset;\r
++              }\r
++\r
++      if (meta)\r
++              meta->locked = 1;\r
++\r
++not_allocated:\r
++      mutex_unlock(&msblk->meta_index_mutex);\r
++\r
++      return meta;\r
++}\r
++\r
++\r
++struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)\r
++{\r
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
++      struct meta_index *meta = NULL;\r
++      int i;\r
++\r
++      mutex_lock(&msblk->meta_index_mutex);\r
++\r
++      TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);\r
++\r
++      if(msblk->meta_index == NULL) {\r
++              if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *\r
++                                      SQUASHFS_META_NUMBER, GFP_KERNEL))) {\r
++                      ERROR("Failed to allocate meta_index\n");\r
++                      goto failed;\r
++              }\r
++              for(i = 0; i < SQUASHFS_META_NUMBER; i++) {\r
++                      msblk->meta_index[i].inode_number = 0;\r
++                      msblk->meta_index[i].locked = 0;\r
++              }\r
++              msblk->next_meta_index = 0;\r
++      }\r
++\r
++      for(i = SQUASHFS_META_NUMBER; i &&\r
++                      msblk->meta_index[msblk->next_meta_index].locked; i --)\r
++              msblk->next_meta_index = (msblk->next_meta_index + 1) %\r
++                      SQUASHFS_META_NUMBER;\r
++\r
++      if(i == 0) {\r
++              TRACE("empty_meta_index: failed!\n");\r
++              goto failed;\r
++      }\r
++\r
++      TRACE("empty_meta_index: returned meta entry %d, %p\n",\r
++                      msblk->next_meta_index,\r
++                      &msblk->meta_index[msblk->next_meta_index]);\r
++\r
++      meta = &msblk->meta_index[msblk->next_meta_index];\r
++      msblk->next_meta_index = (msblk->next_meta_index + 1) %\r
++                      SQUASHFS_META_NUMBER;\r
++\r
++      meta->inode_number = inode->i_ino;\r
++      meta->offset = offset;\r
++      meta->skip = skip;\r
++      meta->entries = 0;\r
++      meta->locked = 1;\r
++\r
++failed:\r
++      mutex_unlock(&msblk->meta_index_mutex);\r
++      return meta;\r
++}\r
++\r
++\r
++void release_meta_index(struct inode *inode, struct meta_index *meta)\r
++{\r
++      meta->locked = 0;\r
++      smp_mb();\r
++}\r
++\r
++\r
++static int read_block_index(struct super_block *s, int blocks, char *block_list,\r
++              long long *start_block, int *offset)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      unsigned int *block_listp;\r
++      int block = 0;\r
++      \r
++      if (msblk->swap) {\r
++              char sblock_list[blocks << 2];\r
++\r
++              if (!squashfs_get_cached_block(s, sblock_list, *start_block,\r
++                              *offset, blocks << 2, start_block, offset)) {\r
++                      ERROR("Unable to read block list [%llx:%x]\n",\r
++                              *start_block, *offset);\r
++                      goto failure;\r
++              }\r
++              SQUASHFS_SWAP_INTS(((unsigned int *)block_list),\r
++                              ((unsigned int *)sblock_list), blocks);\r
++      } else\r
++              if (!squashfs_get_cached_block(s, block_list, *start_block,\r
++                              *offset, blocks << 2, start_block, offset)) {\r
++                      ERROR("Unable to read block list [%llx:%x]\n",\r
++                              *start_block, *offset);\r
++                      goto failure;\r
++              }\r
++\r
++      for (block_listp = (unsigned int *) block_list; blocks;\r
++                              block_listp++, blocks --)\r
++              block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);\r
++\r
++      return block;\r
++\r
++failure:\r
++      return -1;\r
++}\r
++\r
++\r
++#define SIZE 256\r
++\r
++static inline int calculate_skip(int blocks) {\r
++      int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);\r
++      return skip >= 7 ? 7 : skip + 1;\r
++}\r
++\r
++\r
++static int get_meta_index(struct inode *inode, int index,\r
++              long long *index_block, int *index_offset,\r
++              long long *data_block, char *block_list)\r
++{\r
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);\r
++      int offset = 0;\r
++      struct meta_index *meta;\r
++      struct meta_entry *meta_entry;\r
++      long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;\r
++      int cur_offset = SQUASHFS_I(inode)->offset;\r
++      long long cur_data_block = SQUASHFS_I(inode)->start_block;\r
++      int i;\r
++ \r
++      index /= SQUASHFS_META_INDEXES * skip;\r
++\r
++      while ( offset < index ) {\r
++              meta = locate_meta_index(inode, index, offset + 1);\r
++\r
++              if (meta == NULL) {\r
++                      if ((meta = empty_meta_index(inode, offset + 1,\r
++                                                      skip)) == NULL)\r
++                              goto all_done;\r
++              } else {\r
++                      if(meta->entries == 0)\r
++                              goto failed;\r
++                      offset = index < meta->offset + meta->entries ? index :\r
++                              meta->offset + meta->entries - 1;\r
++                      meta_entry = &meta->meta_entry[offset - meta->offset];\r
++                      cur_index_block = meta_entry->index_block + sblk->inode_table_start;\r
++                      cur_offset = meta_entry->offset;\r
++                      cur_data_block = meta_entry->data_block;\r
++                      TRACE("get_meta_index: offset %d, meta->offset %d, "\r
++                              "meta->entries %d\n", offset, meta->offset,\r
++                              meta->entries);\r
++                      TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"\r
++                              " data_block 0x%llx\n", cur_index_block,\r
++                              cur_offset, cur_data_block);\r
++              }\r
++\r
++              for (i = meta->offset + meta->entries; i <= index &&\r
++                              i < meta->offset + SQUASHFS_META_ENTRIES; i++) {\r
++                      int blocks = skip * SQUASHFS_META_INDEXES;\r
++\r
++                      while (blocks) {\r
++                              int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :\r
++                                      blocks;\r
++                              int res = read_block_index(inode->i_sb, block,\r
++                                      block_list, &cur_index_block,\r
++                                      &cur_offset);\r
++\r
++                              if (res == -1)\r
++                                      goto failed;\r
++\r
++                              cur_data_block += res;\r
++                              blocks -= block;\r
++                      }\r
++\r
++                      meta_entry = &meta->meta_entry[i - meta->offset];\r
++                      meta_entry->index_block = cur_index_block - sblk->inode_table_start;\r
++                      meta_entry->offset = cur_offset;\r
++                      meta_entry->data_block = cur_data_block;\r
++                      meta->entries ++;\r
++                      offset ++;\r
++              }\r
++\r
++              TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",\r
++                              meta->offset, meta->entries);\r
++\r
++              release_meta_index(inode, meta);\r
++      }\r
++\r
++all_done:\r
++      *index_block = cur_index_block;\r
++      *index_offset = cur_offset;\r
++      *data_block = cur_data_block;\r
++\r
++      return offset * SQUASHFS_META_INDEXES * skip;\r
++\r
++failed:\r
++      release_meta_index(inode, meta);\r
++      return -1;\r
++}\r
++\r
++\r
++static long long read_blocklist(struct inode *inode, int index,\r
++                              int readahead_blks, char *block_list,\r
++                              unsigned short **block_p, unsigned int *bsize)\r
++{\r
++      long long block_ptr;\r
++      int offset;\r
++      long long block;\r
++      int res = get_meta_index(inode, index, &block_ptr, &offset, &block,\r
++              block_list);\r
++\r
++      TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"\r
++                     " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,\r
++                     block);\r
++\r
++      if(res == -1)\r
++              goto failure;\r
++\r
++      index -= res;\r
++\r
++      while ( index ) {\r
++              int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;\r
++              int res = read_block_index(inode->i_sb, blocks, block_list,\r
++                      &block_ptr, &offset);\r
++              if (res == -1)\r
++                      goto failure;\r
++              block += res;\r
++              index -= blocks;\r
++      }\r
++\r
++      if (read_block_index(inode->i_sb, 1, block_list,\r
++                      &block_ptr, &offset) == -1)\r
++              goto failure;\r
++      *bsize = *((unsigned int *) block_list);\r
++\r
++      return block;\r
++\r
++failure:\r
++      return 0;\r
++}\r
++\r
++\r
++static int squashfs_readpage(struct file *file, struct page *page)\r
++{\r
++      struct inode *inode = page->mapping->host;\r
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      unsigned char *block_list;\r
++      long long block;\r
++      unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;\r
++      int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);\r
++      void *pageaddr;\r
++      struct squashfs_fragment_cache *fragment = NULL;\r
++      char *data_ptr = msblk->read_page;\r
++      \r
++      int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;\r
++      int start_index = page->index & ~mask;\r
++      int end_index = start_index | mask;\r
++\r
++      TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",\r
++                                      page->index,\r
++                                      SQUASHFS_I(inode)->start_block);\r
++\r
++      if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate block_list\n");\r
++              goto skip_read;\r
++      }\r
++\r
++      if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>\r
++                                      PAGE_CACHE_SHIFT))\r
++              goto skip_read;\r
++\r
++      if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK\r
++                                      || index < (i_size_read(inode) >>\r
++                                      sblk->block_log)) {\r
++              if ((block = (msblk->read_blocklist)(inode, index, 1,\r
++                                      block_list, NULL, &bsize)) == 0)\r
++                      goto skip_read;\r
++\r
++              mutex_lock(&msblk->read_page_mutex);\r
++              \r
++              if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,\r
++                                      block, bsize, NULL, sblk->block_size))) {\r
++                      ERROR("Unable to read page, block %llx, size %x\n", block,\r
++                                      bsize);\r
++                      mutex_unlock(&msblk->read_page_mutex);\r
++                      goto skip_read;\r
++              }\r
++      } else {\r
++              if ((fragment = get_cached_fragment(inode->i_sb,\r
++                                      SQUASHFS_I(inode)->\r
++                                      u.s1.fragment_start_block,\r
++                                      SQUASHFS_I(inode)->u.s1.fragment_size))\r
++                                      == NULL) {\r
++                      ERROR("Unable to read page, block %llx, size %x\n",\r
++                                      SQUASHFS_I(inode)->\r
++                                      u.s1.fragment_start_block,\r
++                                      (int) SQUASHFS_I(inode)->\r
++                                      u.s1.fragment_size);\r
++                      goto skip_read;\r
++              }\r
++              bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +\r
++                                      (i_size_read(inode) & (sblk->block_size\r
++                                      - 1));\r
++              byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;\r
++              data_ptr = fragment->data;\r
++      }\r
++\r
++      for (i = start_index; i <= end_index && byte_offset < bytes;\r
++                                      i++, byte_offset += PAGE_CACHE_SIZE) {\r
++              struct page *push_page;\r
++              int avail = (bytes - byte_offset) > PAGE_CACHE_SIZE ?\r
++                                      PAGE_CACHE_SIZE : bytes - byte_offset;\r
++\r
++              TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",\r
++                                      bytes, i, byte_offset, avail);\r
++\r
++              push_page = (i == page->index) ? page :\r
++                      grab_cache_page_nowait(page->mapping, i);\r
++\r
++              if (!push_page)\r
++                      continue;\r
++\r
++              if (PageUptodate(push_page))\r
++                      goto skip_page;\r
++\r
++              pageaddr = kmap_atomic(push_page, KM_USER0);\r
++              memcpy(pageaddr, data_ptr + byte_offset, avail);\r
++              memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);\r
++              kunmap_atomic(pageaddr, KM_USER0);\r
++              flush_dcache_page(push_page);\r
++              SetPageUptodate(push_page);\r
++skip_page:\r
++              unlock_page(push_page);\r
++              if(i != page->index)\r
++                      page_cache_release(push_page);\r
++      }\r
++\r
++      if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK\r
++                                      || index < (i_size_read(inode) >>\r
++                                      sblk->block_log))\r
++              mutex_unlock(&msblk->read_page_mutex);\r
++      else\r
++              release_cached_fragment(msblk, fragment);\r
++\r
++      kfree(block_list);\r
++      return 0;\r
++\r
++skip_read:\r
++      pageaddr = kmap_atomic(page, KM_USER0);\r
++      memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);\r
++      kunmap_atomic(pageaddr, KM_USER0);\r
++      flush_dcache_page(page);\r
++      SetPageUptodate(page);\r
++      unlock_page(page);\r
++\r
++      kfree(block_list);\r
++      return 0;\r
++}\r
++\r
++\r
++static int squashfs_readpage4K(struct file *file, struct page *page)\r
++{\r
++      struct inode *inode = page->mapping->host;\r
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      unsigned char *block_list;\r
++      long long block;\r
++      unsigned int bsize, bytes = 0;\r
++      void *pageaddr;\r
++      \r
++      TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",\r
++                                      page->index,\r
++                                      SQUASHFS_I(inode)->start_block);\r
++\r
++      if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>\r
++                                      PAGE_CACHE_SHIFT)) {\r
++              block_list = NULL;\r
++              goto skip_read;\r
++      }\r
++\r
++      if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate block_list\n");\r
++              goto skip_read;\r
++      }\r
++\r
++      if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK\r
++                                      || page->index < (i_size_read(inode) >>\r
++                                      sblk->block_log)) {\r
++              block = (msblk->read_blocklist)(inode, page->index, 1,\r
++                                      block_list, NULL, &bsize);\r
++              if(block == 0)\r
++                      goto skip_read;\r
++\r
++              mutex_lock(&msblk->read_page_mutex);\r
++              bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,\r
++                                      bsize, NULL, sblk->block_size);\r
++              if (bytes) {\r
++                      pageaddr = kmap_atomic(page, KM_USER0);\r
++                      memcpy(pageaddr, msblk->read_page, bytes);\r
++                      kunmap_atomic(pageaddr, KM_USER0);\r
++              } else\r
++                      ERROR("Unable to read page, block %llx, size %x\n",\r
++                                      block, bsize);\r
++              mutex_unlock(&msblk->read_page_mutex);\r
++      } else {\r
++              struct squashfs_fragment_cache *fragment =\r
++                      get_cached_fragment(inode->i_sb,\r
++                                      SQUASHFS_I(inode)->\r
++                                      u.s1.fragment_start_block,\r
++                                      SQUASHFS_I(inode)-> u.s1.fragment_size);\r
++              if (fragment) {\r
++                      bytes = i_size_read(inode) & (sblk->block_size - 1);\r
++                      pageaddr = kmap_atomic(page, KM_USER0);\r
++                      memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->\r
++                                      u.s1.fragment_offset, bytes);\r
++                      kunmap_atomic(pageaddr, KM_USER0);\r
++                      release_cached_fragment(msblk, fragment);\r
++              } else\r
++                      ERROR("Unable to read page, block %llx, size %x\n",\r
++                                      SQUASHFS_I(inode)->\r
++                                      u.s1.fragment_start_block, (int)\r
++                                      SQUASHFS_I(inode)-> u.s1.fragment_size);\r
++      }\r
++\r
++skip_read:\r
++      pageaddr = kmap_atomic(page, KM_USER0);\r
++      memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);\r
++      kunmap_atomic(pageaddr, KM_USER0);\r
++      flush_dcache_page(page);\r
++      SetPageUptodate(page);\r
++      unlock_page(page);\r
++\r
++      kfree(block_list);\r
++      return 0;\r
++}\r
++\r
++\r
++static int get_dir_index_using_offset(struct super_block *s, long long \r
++                              *next_block, unsigned int *next_offset,\r
++                              long long index_start,\r
++                              unsigned int index_offset, int i_count,\r
++                              long long f_pos)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      int i, length = 0;\r
++      struct squashfs_dir_index index;\r
++\r
++      TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",\r
++                                      i_count, (unsigned int) f_pos);\r
++\r
++      f_pos =- 3;\r
++      if (f_pos == 0)\r
++              goto finish;\r
++\r
++      for (i = 0; i < i_count; i++) {\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_index sindex;\r
++                      squashfs_get_cached_block(s, (char *) &sindex,\r
++                                      index_start, index_offset,\r
++                                      sizeof(sindex), &index_start,\r
++                                      &index_offset);\r
++                      SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);\r
++              } else\r
++                      squashfs_get_cached_block(s, (char *) &index,\r
++                                      index_start, index_offset,\r
++                                      sizeof(index), &index_start,\r
++                                      &index_offset);\r
++\r
++              if (index.index > f_pos)\r
++                      break;\r
++\r
++              squashfs_get_cached_block(s, NULL, index_start, index_offset,\r
++                                      index.size + 1, &index_start,\r
++                                      &index_offset);\r
++\r
++              length = index.index;\r
++              *next_block = index.start_block + sblk->directory_table_start;\r
++      }\r
++\r
++      *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;\r
++\r
++finish:\r
++      return length + 3;\r
++}\r
++\r
++\r
++static int get_dir_index_using_name(struct super_block *s, long long\r
++                              *next_block, unsigned int *next_offset,\r
++                              long long index_start,\r
++                              unsigned int index_offset, int i_count,\r
++                              const char *name, int size)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      int i, length = 0;\r
++      struct squashfs_dir_index *index;\r
++      char *str;\r
++\r
++      TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);\r
++\r
++      if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +\r
++              (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate squashfs_dir_index\n");\r
++              goto failure;\r
++      }\r
++\r
++      index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1);\r
++      strncpy(str, name, size);\r
++      str[size] = '\0';\r
++\r
++      for (i = 0; i < i_count; i++) {\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_index sindex;\r
++                      squashfs_get_cached_block(s, (char *) &sindex,\r
++                                      index_start, index_offset,\r
++                                      sizeof(sindex), &index_start,\r
++                                      &index_offset);\r
++                      SQUASHFS_SWAP_DIR_INDEX(index, &sindex);\r
++              } else\r
++                      squashfs_get_cached_block(s, (char *) index,\r
++                                      index_start, index_offset,\r
++                                      sizeof(struct squashfs_dir_index),\r
++                                      &index_start, &index_offset);\r
++\r
++              squashfs_get_cached_block(s, index->name, index_start,\r
++                                      index_offset, index->size + 1,\r
++                                      &index_start, &index_offset);\r
++\r
++              index->name[index->size + 1] = '\0';\r
++\r
++              if (strcmp(index->name, str) > 0)\r
++                      break;\r
++\r
++              length = index->index;\r
++              *next_block = index->start_block + sblk->directory_table_start;\r
++      }\r
++\r
++      *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;\r
++      kfree(str);\r
++failure:\r
++      return length + 3;\r
++}\r
++\r
++              \r
++static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)\r
++{\r
++      struct inode *i = file->f_dentry->d_inode;\r
++      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      long long next_block = SQUASHFS_I(i)->start_block +\r
++              sblk->directory_table_start;\r
++      int next_offset = SQUASHFS_I(i)->offset, length = 0,\r
++              dir_count;\r
++      struct squashfs_dir_header dirh;\r
++      struct squashfs_dir_entry *dire;\r
++\r
++      TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);\r
++\r
++      if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +\r
++              SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate squashfs_dir_entry\n");\r
++              goto finish;\r
++      }\r
++\r
++      while(file->f_pos < 3) {\r
++              char *name;\r
++              int size, i_ino;\r
++\r
++              if(file->f_pos == 0) {\r
++                      name = ".";\r
++                      size = 1;\r
++                      i_ino = i->i_ino;\r
++              } else {\r
++                      name = "..";\r
++                      size = 2;\r
++                      i_ino = SQUASHFS_I(i)->u.s2.parent_inode;\r
++              }\r
++              TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",\r
++                              (unsigned int) dirent, name, size, (int)\r
++                              file->f_pos, i_ino,\r
++                              squashfs_filetype_table[1]);\r
++\r
++              if (filldir(dirent, name, size,\r
++                              file->f_pos, i_ino,\r
++                              squashfs_filetype_table[1]) < 0) {\r
++                              TRACE("Filldir returned less than 0\n");\r
++                              goto finish;\r
++              }\r
++              file->f_pos += size;\r
++      }\r
++\r
++      length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_start,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_count,\r
++                              file->f_pos);\r
++\r
++      while (length < i_size_read(i)) {\r
++              /* read directory header */\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_header sdirh;\r
++                      \r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,\r
++                                      next_block, next_offset, sizeof(sdirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(sdirh);\r
++                      SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);\r
++              } else {\r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,\r
++                                      next_block, next_offset, sizeof(dirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(dirh);\r
++              }\r
++\r
++              dir_count = dirh.count + 1;\r
++              while (dir_count--) {\r
++                      if (msblk->swap) {\r
++                              struct squashfs_dir_entry sdire;\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              &sdire, next_block, next_offset,\r
++                                              sizeof(sdire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              \r
++                              length += sizeof(sdire);\r
++                              SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);\r
++                      } else {\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              dire, next_block, next_offset,\r
++                                              sizeof(*dire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                              length += sizeof(*dire);\r
++                      }\r
++\r
++                      if (!squashfs_get_cached_block(i->i_sb, dire->name,\r
++                                              next_block, next_offset,\r
++                                              dire->size + 1, &next_block,\r
++                                              &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += dire->size + 1;\r
++\r
++                      if (file->f_pos >= length)\r
++                              continue;\r
++\r
++                      dire->name[dire->size + 1] = '\0';\r
++\r
++                      TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",\r
++                                      (unsigned int) dirent, dire->name,\r
++                                      dire->size + 1, (int) file->f_pos,\r
++                                      dirh.start_block, dire->offset,\r
++                                      dirh.inode_number + dire->inode_number,\r
++                                      squashfs_filetype_table[dire->type]);\r
++\r
++                      if (filldir(dirent, dire->name, dire->size + 1,\r
++                                      file->f_pos,\r
++                                      dirh.inode_number + dire->inode_number,\r
++                                      squashfs_filetype_table[dire->type])\r
++                                      < 0) {\r
++                              TRACE("Filldir returned less than 0\n");\r
++                              goto finish;\r
++                      }\r
++                      file->f_pos = length;\r
++              }\r
++      }\r
++\r
++finish:\r
++      kfree(dire);\r
++      return 0;\r
++\r
++failed_read:\r
++      ERROR("Unable to read directory block [%llx:%x]\n", next_block,\r
++              next_offset);\r
++      kfree(dire);\r
++      return 0;\r
++}\r
++\r
++\r
++static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,\r
++                              struct nameidata *nd)\r
++{\r
++      const unsigned char *name = dentry->d_name.name;\r
++      int len = dentry->d_name.len;\r
++      struct inode *inode = NULL;\r
++      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      long long next_block = SQUASHFS_I(i)->start_block +\r
++                              sblk->directory_table_start;\r
++      int next_offset = SQUASHFS_I(i)->offset, length = 0,\r
++                              dir_count;\r
++      struct squashfs_dir_header dirh;\r
++      struct squashfs_dir_entry *dire;\r
++\r
++      TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);\r
++\r
++      if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +\r
++              SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate squashfs_dir_entry\n");\r
++              goto exit_lookup;\r
++      }\r
++\r
++      if (len > SQUASHFS_NAME_LEN)\r
++              goto exit_lookup;\r
++\r
++      length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_start,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_count, name,\r
++                              len);\r
++\r
++      while (length < i_size_read(i)) {\r
++              /* read directory header */\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_header sdirh;\r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,\r
++                                      next_block, next_offset, sizeof(sdirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(sdirh);\r
++                      SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);\r
++              } else {\r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,\r
++                                      next_block, next_offset, sizeof(dirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(dirh);\r
++              }\r
++\r
++              dir_count = dirh.count + 1;\r
++              while (dir_count--) {\r
++                      if (msblk->swap) {\r
++                              struct squashfs_dir_entry sdire;\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              &sdire, next_block,next_offset,\r
++                                              sizeof(sdire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              \r
++                              length += sizeof(sdire);\r
++                              SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);\r
++                      } else {\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              dire, next_block,next_offset,\r
++                                              sizeof(*dire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                              length += sizeof(*dire);\r
++                      }\r
++\r
++                      if (!squashfs_get_cached_block(i->i_sb, dire->name,\r
++                                      next_block, next_offset, dire->size + 1,\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += dire->size + 1;\r
++\r
++                      if (name[0] < dire->name[0])\r
++                              goto exit_lookup;\r
++\r
++                      if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) {\r
++                              squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block,\r
++                                                              dire->offset);\r
++\r
++                              TRACE("calling squashfs_iget for directory "\r
++                                      "entry %s, inode %x:%x, %d\n", name,\r
++                                      dirh.start_block, dire->offset,\r
++                                      dirh.inode_number + dire->inode_number);\r
++\r
++                              inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number);\r
++\r
++                              goto exit_lookup;\r
++                      }\r
++              }\r
++      }\r
++\r
++exit_lookup:\r
++      kfree(dire);\r
++      if (inode)\r
++              return d_splice_alias(inode, dentry);\r
++      d_add(dentry, inode);\r
++      return ERR_PTR(0);\r
++\r
++failed_read:\r
++      ERROR("Unable to read directory block [%llx:%x]\n", next_block,\r
++              next_offset);\r
++      goto exit_lookup;\r
++}\r
++\r
++\r
++static int squashfs_remount(struct super_block *s, int *flags, char *data)\r
++{\r
++      *flags |= MS_RDONLY;\r
++      return 0;\r
++}\r
++\r
++\r
++static void squashfs_put_super(struct super_block *s)\r
++{\r
++      int i;\r
++\r
++      if (s->s_fs_info) {\r
++              struct squashfs_sb_info *sbi = s->s_fs_info;\r
++              if (sbi->block_cache)\r
++                      for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)\r
++                              if (sbi->block_cache[i].block !=\r
++                                                      SQUASHFS_INVALID_BLK)\r
++                                      kfree(sbi->block_cache[i].data);\r
++              if (sbi->fragment)\r
++                      for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) \r
++                              SQUASHFS_FREE(sbi->fragment[i].data);\r
++              kfree(sbi->fragment);\r
++              kfree(sbi->block_cache);\r
++              kfree(sbi->read_page);\r
++              kfree(sbi->uid);\r
++              kfree(sbi->fragment_index);\r
++              kfree(sbi->fragment_index_2);\r
++              kfree(sbi->meta_index);\r
++              kfree(s->s_fs_info);\r
++              s->s_fs_info = NULL;\r
++      }\r
++}\r
++\r
++\r
++static int squashfs_get_sb(struct file_system_type *fs_type, int flags,\r
++                              const char *dev_name, void *data,\r
++                              struct vfsmount *mnt)\r
++{\r
++      return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,\r
++                              mnt);\r
++}\r
++\r
++\r
++static void free_sqlzma(void)\r
++{\r
++      int cpu;\r
++      struct sqlzma *p;\r
++\r
++      for_each_online_cpu(cpu) {\r
++              p = per_cpu(sqlzma, cpu);\r
++              if (p) {\r
++#ifdef KeepPreemptive\r
++                      mutex_destroy(&p->mtx);\r
++#endif\r
++                      sqlzma_fin(&p->un);\r
++                      kfree(p);\r
++              }\r
++      }\r
++}\r
++\r
++static int __init init_squashfs_fs(void)\r
++{\r
++      struct sqlzma *p;\r
++      int cpu;\r
++      int err = init_inodecache();\r
++      if (err)\r
++              goto out;\r
++\r
++      for_each_online_cpu(cpu) {\r
++              dpri("%d: %p\n", cpu, per_cpu(sqlzma, cpu));\r
++              err = -ENOMEM;\r
++              p = kmalloc(sizeof(struct sqlzma), GFP_KERNEL);\r
++              if (p) {\r
++#ifdef KeepPreemptive\r
++                      mutex_init(&p->mtx);\r
++#endif\r
++                      err = sqlzma_init(&p->un, 1, 0);\r
++                      if (unlikely(err)) {\r
++                              ERROR("Failed to intialize uncompress workspace\n");\r
++                              break;\r
++                      }\r
++                      per_cpu(sqlzma, cpu) = p;\r
++                      err = 0;\r
++              } else\r
++                      break;\r
++      }\r
++      if (unlikely(err)) {\r
++              free_sqlzma();\r
++              goto out;\r
++      }\r
++\r
++      printk(KERN_INFO "squashfs: version 3.2-r2 (2007/01/15) "\r
++              "Phillip Lougher\n"\r
++              "squashfs: LZMA suppport for slax.org by jro\n");\r
++\r
++      if ((err = register_filesystem(&squashfs_fs_type))) {\r
++              free_sqlzma();\r
++              destroy_inodecache();\r
++      }\r
++\r
++out:\r
++      return err;\r
++}\r
++\r
++\r
++static void __exit exit_squashfs_fs(void)\r
++{\r
++      unregister_filesystem(&squashfs_fs_type);\r
++      free_sqlzma();\r
++      destroy_inodecache();\r
++}\r
++\r
++\r
++static struct kmem_cache * squashfs_inode_cachep;\r
++\r
++\r
++static struct inode *squashfs_alloc_inode(struct super_block *sb)\r
++{\r
++      struct squashfs_inode_info *ei;\r
++      ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);\r
++      if (!ei)\r
++              return NULL;\r
++      return &ei->vfs_inode;\r
++}\r
++\r
++\r
++static void squashfs_destroy_inode(struct inode *inode)\r
++{\r
++      kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));\r
++}\r
++\r
++\r
++static void init_once(struct kmem_cache * cachep, void * foo)\r
++{\r
++      struct squashfs_inode_info *ei = foo;\r
++              inode_init_once(&ei->vfs_inode);\r
++}\r
++ \r
++\r
++static int __init init_inodecache(void)\r
++{\r
++      squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",\r
++           sizeof(struct squashfs_inode_info),\r
++           0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,\r
++           init_once);\r
++      if (squashfs_inode_cachep == NULL)\r
++              return -ENOMEM;\r
++      return 0;\r
++}\r
++\r
++\r
++static void destroy_inodecache(void)\r
++{\r
++      kmem_cache_destroy(squashfs_inode_cachep);\r
++}\r
++\r
++\r
++module_init(init_squashfs_fs);\r
++module_exit(exit_squashfs_fs);\r
++MODULE_DESCRIPTION("squashfs 3.2-r2, a compressed read-only filesystem, and LZMA suppport for slax.org");\r
++MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>, and LZMA suppport for slax.org by jro");\r
++MODULE_LICENSE("GPL");\r
+diff -urN linux-2.6.23/fs/squashfs/module.c linux-2.6.23.sqlzma/fs/squashfs/module.c\r
+--- linux-2.6.23/fs/squashfs/module.c  1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/module.c   2007-10-14 12:58:25.000000000 -0400\r
+@@ -0,0 +1,36 @@\r
++\r
++/*\r
++ * Copyright (C) 2006 Junjiro Okajima\r
++ * Copyright (C) 2006 Tomas Matejicek, slax.org\r
++ *\r
++ * LICENSE follows the described one in lzma.txt.\r
++ */\r
++\r
++/* $Id: module.c,v 1.5 2006/11/27 03:54:58 jro Exp $ */\r
++\r
++#include <linux/init.h>\r
++#include <linux/module.h>\r
++\r
++#include "LzmaDecode.c"\r
++\r
++EXPORT_SYMBOL(LzmaDecodeProperties);\r
++EXPORT_SYMBOL(LzmaDecode);\r
++\r
++#if 0\r
++static int __init unlzma_init(void)\r
++{\r
++      return 0;\r
++}\r
++\r
++static void __exit unlzma_exit(void)\r
++{\r
++}\r
++\r
++module_init(unlzma_init);\r
++module_exit(unlzma_exit);\r
++#endif\r
++\r
++MODULE_LICENSE("GPL");\r
++MODULE_VERSION("$Id: module.c,v 1.5 2006/11/27 03:54:58 jro Exp $");\r
++MODULE_DESCRIPTION("LZMA uncompress. "\r
++                 "A tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org.");\r
+diff -urN linux-2.6.23/fs/squashfs/sqlzma.h linux-2.6.23.sqlzma/fs/squashfs/sqlzma.h\r
+--- linux-2.6.23/fs/squashfs/sqlzma.h  1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/sqlzma.h   2007-10-14 13:07:12.000000000 -0400\r
+@@ -0,0 +1,79 @@\r
++/*\r
++ * Copyright (C) 2006 Junjiro Okajima\r
++ * Copyright (C) 2006 Tomas Matejicek, slax.org\r
++ *\r
++ * LICENSE follows the described one in lzma.\r
++ */\r
++\r
++/* $Id: sqlzma.h,v 1.13 2007/01/07 15:12:48 jro Exp $ */\r
++\r
++#ifndef __sqlzma_h__\r
++#define __sqlzma_h__\r
++\r
++#ifndef __KERNEL__\r
++#include <stdlib.h>\r
++#include <string.h>\r
++#include <zlib.h>\r
++#ifdef _REENTRANT\r
++#include <pthread.h>\r
++#endif\r
++#else\r
++#include <linux/zlib.h>\r
++#endif\r
++#define _7ZIP_BYTE_DEFINED\r
++\r
++/*\r
++ * detect the compression method automatically by the first byte of compressed\r
++ * data.\r
++ * according to rfc1950, the first byte of zlib compression must be 0x?8.\r
++ */\r
++#define is_lzma(c)    (c == 0x5d)\r
++\r
++/* ---------------------------------------------------------------------- */\r
++\r
++#ifdef __cplusplus\r
++extern "C" {\r
++#endif\r
++\r
++#ifndef __KERNEL__\r
++/* for mksquashfs only */\r
++int sqlzma_cm(int lzma, z_stream *stream, Bytef *next_in, uInt avail_in,\r
++            Bytef *next_out, uInt avail_out);\r
++#endif\r
++\r
++/* ---------------------------------------------------------------------- */\r
++/*\r
++ * Three patterns for sqlzma uncompression. very dirty code.\r
++ * - kernel space (squashfs kernel module)\r
++ * - user space with pthread (mksquashfs)\r
++ * - user space without pthread (unsquashfs)\r
++ */\r
++\r
++struct sized_buf {\r
++      unsigned int    sz;\r
++      unsigned char   *buf;\r
++};\r
++\r
++enum {SQUN_PROB, SQUN_RESULT, SQUN_LAST};\r
++struct sqlzma_un {\r
++      int                     un_lzma;\r
++      struct sized_buf        un_a[SQUN_LAST];\r
++      unsigned char           un_prob[31960]; /* unlzma 64KB */\r
++      z_stream                un_stream;\r
++#define un_cmbuf      un_stream.next_in\r
++#define un_cmlen      un_stream.avail_in\r
++#define un_resbuf     un_stream.next_out\r
++#define un_resroom    un_stream.avail_out\r
++#define un_reslen     un_stream.total_out\r
++};\r
++\r
++int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz);\r
++int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst);\r
++void sqlzma_fin(struct sqlzma_un *un);\r
++\r
++/* ---------------------------------------------------------------------- */\r
++\r
++#ifdef __cplusplus\r
++};\r
++#endif\r
++#endif\r
+diff -urN linux-2.6.23/fs/squashfs/sqmagic.h linux-2.6.23.sqlzma/fs/squashfs/sqmagic.h\r
+--- linux-2.6.23/fs/squashfs/sqmagic.h 1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/sqmagic.h  2007-10-14 14:32:24.000000000 -0400\r
+@@ -0,0 +1,17 @@\r
++/*\r
++ * Copyright (C) 2006 Junjiro Okajima\r
++ * Copyright (C) 2006 Tomas Matejicek, slax.org\r
++ *\r
++ * LICENSE must follow the one in squashfs.\r
++ */\r
++\r
++/* $Id: sqmagic.h,v 1.2 2006/11/27 03:54:58 jro Exp $ */\r
++\r
++#ifndef __sqmagic_h__\r
++#define __sqmagic_h__\r
++\r
++/* see SQUASHFS_MAGIC in squashfs_fs.h */\r
++#define SQUASHFS_MAGIC_LZMA           0x71736873\r
++#define SQUASHFS_MAGIC_LZMA_SWAP      0x73687371\r
++\r
++#endif\r
+diff -urN linux-2.6.23/fs/squashfs/squashfs.h linux-2.6.23.sqlzma/fs/squashfs/squashfs.h\r
+--- linux-2.6.23/fs/squashfs/squashfs.h        1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/squashfs.h 2007-10-14 10:24:31.000000000 -0400\r
+@@ -0,0 +1,87 @@\r
++/*\r
++ * Squashfs - a compressed read only filesystem for Linux\r
++ *\r
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
++ * Phillip Lougher <phillip@lougher.org.uk>\r
++ *\r
++ * This program is free software; you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License\r
++ * as published by the Free Software Foundation; either version 2,\r
++ * or (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program; if not, write to the Free Software\r
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
++ *\r
++ * squashfs.h\r
++ */\r
++\r
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY\r
++#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY\r
++#endif\r
++\r
++#ifdef SQUASHFS_TRACE\r
++#define TRACE(s, args...)     printk(KERN_NOTICE "SQUASHFS: "s, ## args)\r
++#else\r
++#define TRACE(s, args...)     {}\r
++#endif\r
++\r
++#define ERROR(s, args...)     printk(KERN_ERR "SQUASHFS error: "s, ## args)\r
++\r
++#define SERROR(s, args...)    do { \\r
++                              if (!silent) \\r
++                              printk(KERN_ERR "SQUASHFS error: "s, ## args);\\r
++                              } while(0)\r
++\r
++#define WARNING(s, args...)   printk(KERN_WARNING "SQUASHFS: "s, ## args)\r
++\r
++static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)\r
++{\r
++      return list_entry(inode, struct squashfs_inode_info, vfs_inode);\r
++}\r
++\r
++#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)\r
++#define SQSH_EXTERN\r
++extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,\r
++                              long long index, unsigned int length,\r
++                              long long *next_index, int srclength);\r
++extern int squashfs_get_cached_block(struct super_block *s, char *buffer,\r
++                              long long block, unsigned int offset,\r
++                              int length, long long *next_block,\r
++                              unsigned int *next_offset);\r
++extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct\r
++                                      squashfs_fragment_cache *fragment);\r
++extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block\r
++                                      *s, long long start_block,\r
++                                      int length);\r
++extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number);\r
++extern const struct address_space_operations squashfs_symlink_aops;\r
++extern const struct address_space_operations squashfs_aops;\r
++extern const struct address_space_operations squashfs_aops_4K;\r
++extern struct inode_operations squashfs_dir_inode_ops;\r
++#else\r
++#define SQSH_EXTERN static\r
++#endif\r
++\r
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY\r
++extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);\r
++#else\r
++static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)\r
++{\r
++      return 0;\r
++}\r
++#endif\r
++\r
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY\r
++extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);\r
++#else\r
++static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)\r
++{\r
++      return 0;\r
++}\r
++#endif\r
+diff -urN linux-2.6.23/fs/squashfs/squashfs2_0.c linux-2.6.23.sqlzma/fs/squashfs/squashfs2_0.c\r
+--- linux-2.6.23/fs/squashfs/squashfs2_0.c     1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/squashfs2_0.c      2007-10-14 10:24:31.000000000 -0400\r
+@@ -0,0 +1,742 @@\r
++/*\r
++ * Squashfs - a compressed read only filesystem for Linux\r
++ *\r
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
++ * Phillip Lougher <phillip@lougher.org.uk>\r
++ *\r
++ * This program is free software; you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License\r
++ * as published by the Free Software Foundation; either version 2,\r
++ * or (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program; if not, write to the Free Software\r
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
++ *\r
++ * squashfs2_0.c\r
++ */\r
++\r
++#include <linux/squashfs_fs.h>\r
++#include <linux/module.h>\r
++#include <linux/zlib.h>\r
++#include <linux/fs.h>\r
++#include <linux/squashfs_fs_sb.h>\r
++#include <linux/squashfs_fs_i.h>\r
++\r
++#include "squashfs.h"\r
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);\r
++static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,\r
++                              struct nameidata *);\r
++\r
++static struct file_operations squashfs_dir_ops_2 = {\r
++      .read = generic_read_dir,\r
++      .readdir = squashfs_readdir_2\r
++};\r
++\r
++static struct inode_operations squashfs_dir_inode_ops_2 = {\r
++      .lookup = squashfs_lookup_2\r
++};\r
++\r
++static unsigned char squashfs_filetype_table[] = {\r
++      DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK\r
++};\r
++\r
++static int read_fragment_index_table_2(struct super_block *s)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++\r
++      if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2\r
++                                      (sblk->fragments), GFP_KERNEL))) {\r
++              ERROR("Failed to allocate uid/gid table\n");\r
++              return 0;\r
++      }\r
++   \r
++      if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&\r
++                                      !squashfs_read_data(s, (char *)\r
++                                      msblk->fragment_index_2,\r
++                                      sblk->fragment_table_start,\r
++                                      SQUASHFS_FRAGMENT_INDEX_BYTES_2\r
++                                      (sblk->fragments) |\r
++                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {\r
++              ERROR("unable to read fragment index table\n");\r
++              return 0;\r
++      }\r
++\r
++      if (msblk->swap) {\r
++              int i;\r
++              unsigned int fragment;\r
++\r
++              for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);\r
++                                                                      i++) {\r
++                      SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),\r
++                                              &msblk->fragment_index_2[i], 1);\r
++                      msblk->fragment_index_2[i] = fragment;\r
++              }\r
++      }\r
++\r
++      return 1;\r
++}\r
++\r
++\r
++static int get_fragment_location_2(struct super_block *s, unsigned int fragment,\r
++                              long long *fragment_start_block,\r
++                              unsigned int *fragment_size)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      long long start_block =\r
++              msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];\r
++      int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);\r
++      struct squashfs_fragment_entry_2 fragment_entry;\r
++\r
++      if (msblk->swap) {\r
++              struct squashfs_fragment_entry_2 sfragment_entry;\r
++\r
++              if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,\r
++                                      start_block, offset,\r
++                                      sizeof(sfragment_entry), &start_block,\r
++                                      &offset))\r
++                      goto out;\r
++              SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);\r
++      } else\r
++              if (!squashfs_get_cached_block(s, (char *) &fragment_entry,\r
++                                      start_block, offset,\r
++                                      sizeof(fragment_entry), &start_block,\r
++                                      &offset))\r
++                      goto out;\r
++\r
++      *fragment_start_block = fragment_entry.start_block;\r
++      *fragment_size = fragment_entry.size;\r
++\r
++      return 1;\r
++\r
++out:\r
++      return 0;\r
++}\r
++\r
++\r
++static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,\r
++              struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)\r
++{\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++\r
++      i->i_ino = ino;\r
++      i->i_mtime.tv_sec = sblk->mkfs_time;\r
++      i->i_atime.tv_sec = sblk->mkfs_time;\r
++      i->i_ctime.tv_sec = sblk->mkfs_time;\r
++      i->i_uid = msblk->uid[inodeb->uid];\r
++      i->i_mode = inodeb->mode;\r
++      i->i_nlink = 1;\r
++      i->i_size = 0;\r
++      if (inodeb->guid == SQUASHFS_GUIDS)\r
++              i->i_gid = i->i_uid;\r
++      else\r
++              i->i_gid = msblk->guid[inodeb->guid];\r
++}\r
++\r
++\r
++static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode)\r
++{\r
++      struct super_block *s = i->i_sb;\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      unsigned int block = SQUASHFS_INODE_BLK(inode) +\r
++              sblk->inode_table_start;\r
++      unsigned int offset = SQUASHFS_INODE_OFFSET(inode);\r
++      unsigned int ino = i->i_ino;\r
++      long long next_block;\r
++      unsigned int next_offset;\r
++      union squashfs_inode_header_2 id, sid;\r
++      struct squashfs_base_inode_header_2 *inodeb = &id.base,\r
++                                        *sinodeb = &sid.base;\r
++\r
++      TRACE("Entered squashfs_iget\n");\r
++\r
++      if (msblk->swap) {\r
++              if (!squashfs_get_cached_block(s, (char *) sinodeb, block,\r
++                                      offset, sizeof(*sinodeb), &next_block,\r
++                                      &next_offset))\r
++                      goto failed_read;\r
++              SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,\r
++                                      sizeof(*sinodeb));\r
++      } else\r
++              if (!squashfs_get_cached_block(s, (char *) inodeb, block,\r
++                                      offset, sizeof(*inodeb), &next_block,\r
++                                      &next_offset))\r
++                      goto failed_read;\r
++\r
++      squashfs_new_inode(msblk, i, inodeb, ino);\r
++\r
++      switch(inodeb->inode_type) {\r
++              case SQUASHFS_FILE_TYPE: {\r
++                      struct squashfs_reg_inode_header_2 *inodep = &id.reg;\r
++                      struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;\r
++                      long long frag_blk;\r
++                      unsigned int frag_size = 0;\r
++                              \r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      frag_blk = SQUASHFS_INVALID_BLK;\r
++                      if (inodep->fragment != SQUASHFS_INVALID_FRAG &&\r
++                                      !get_fragment_location_2(s,\r
++                                      inodep->fragment, &frag_blk, &frag_size))\r
++                              goto failed_read;\r
++                              \r
++                      i->i_size = inodep->file_size;\r
++                      i->i_fop = &generic_ro_fops;\r
++                      i->i_mode |= S_IFREG;\r
++                      i->i_mtime.tv_sec = inodep->mtime;\r
++                      i->i_atime.tv_sec = inodep->mtime;\r
++                      i->i_ctime.tv_sec = inodep->mtime;\r
++                      i->i_blocks = ((i->i_size - 1) >> 9) + 1;\r
++                      SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;\r
++                      SQUASHFS_I(i)->u.s1.fragment_size = frag_size;\r
++                      SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->u.s1.block_list_start = next_block;\r
++                      SQUASHFS_I(i)->offset = next_offset;\r
++                      if (sblk->block_size > 4096)\r
++                              i->i_data.a_ops = &squashfs_aops;\r
++                      else\r
++                              i->i_data.a_ops = &squashfs_aops_4K;\r
++\r
++                      TRACE("File inode %x:%x, start_block %x, "\r
++                                      "block_list_start %llx, offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->start_block, next_block,\r
++                                      next_offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_DIR_TYPE: {\r
++                      struct squashfs_dir_inode_header_2 *inodep = &id.dir;\r
++                      struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_size = inodep->file_size;\r
++                      i->i_op = &squashfs_dir_inode_ops_2;\r
++                      i->i_fop = &squashfs_dir_ops_2;\r
++                      i->i_mode |= S_IFDIR;\r
++                      i->i_mtime.tv_sec = inodep->mtime;\r
++                      i->i_atime.tv_sec = inodep->mtime;\r
++                      i->i_ctime.tv_sec = inodep->mtime;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->offset = inodep->offset;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_count = 0;\r
++                      SQUASHFS_I(i)->u.s2.parent_inode = 0;\r
++\r
++                      TRACE("Directory inode %x:%x, start_block %x, offset "\r
++                                      "%x\n", SQUASHFS_INODE_BLK(inode),\r
++                                      offset, inodep->start_block,\r
++                                      inodep->offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_LDIR_TYPE: {\r
++                      struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;\r
++                      struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,\r
++                                              sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_size = inodep->file_size;\r
++                      i->i_op = &squashfs_dir_inode_ops_2;\r
++                      i->i_fop = &squashfs_dir_ops_2;\r
++                      i->i_mode |= S_IFDIR;\r
++                      i->i_mtime.tv_sec = inodep->mtime;\r
++                      i->i_atime.tv_sec = inodep->mtime;\r
++                      i->i_ctime.tv_sec = inodep->mtime;\r
++                      SQUASHFS_I(i)->start_block = inodep->start_block;\r
++                      SQUASHFS_I(i)->offset = inodep->offset;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_start = next_block;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_offset =\r
++                                                              next_offset;\r
++                      SQUASHFS_I(i)->u.s2.directory_index_count =\r
++                                                              inodep->i_count;\r
++                      SQUASHFS_I(i)->u.s2.parent_inode = 0;\r
++\r
++                      TRACE("Long directory inode %x:%x, start_block %x, "\r
++                                      "offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->start_block, inodep->offset);\r
++                      break;\r
++              }\r
++              case SQUASHFS_SYMLINK_TYPE: {\r
++                      struct squashfs_symlink_inode_header_2 *inodep =\r
++                                                              &id.symlink;\r
++                      struct squashfs_symlink_inode_header_2 *sinodep =\r
++                                                              &sid.symlink;\r
++      \r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,\r
++                                                              sinodep);\r
++                      } else\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_size = inodep->symlink_size;\r
++                      i->i_op = &page_symlink_inode_operations;\r
++                      i->i_data.a_ops = &squashfs_symlink_aops;\r
++                      i->i_mode |= S_IFLNK;\r
++                      SQUASHFS_I(i)->start_block = next_block;\r
++                      SQUASHFS_I(i)->offset = next_offset;\r
++\r
++                      TRACE("Symbolic link inode %x:%x, start_block %llx, "\r
++                                      "offset %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      next_block, next_offset);\r
++                      break;\r
++               }\r
++               case SQUASHFS_BLKDEV_TYPE:\r
++               case SQUASHFS_CHRDEV_TYPE: {\r
++                      struct squashfs_dev_inode_header_2 *inodep = &id.dev;\r
++                      struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;\r
++\r
++                      if (msblk->swap) {\r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              sinodep, block, offset,\r
++                                              sizeof(*sinodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);\r
++                      } else  \r
++                              if (!squashfs_get_cached_block(s, (char *)\r
++                                              inodep, block, offset,\r
++                                              sizeof(*inodep), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                      i->i_mode |= (inodeb->inode_type ==\r
++                                      SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :\r
++                                      S_IFBLK;\r
++                      init_special_inode(i, i->i_mode,\r
++                                      old_decode_dev(inodep->rdev));\r
++\r
++                      TRACE("Device inode %x:%x, rdev %x\n",\r
++                                      SQUASHFS_INODE_BLK(inode), offset,\r
++                                      inodep->rdev);\r
++                      break;\r
++               }\r
++               case SQUASHFS_FIFO_TYPE:\r
++               case SQUASHFS_SOCKET_TYPE: {\r
++\r
++                      i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)\r
++                                                      ? S_IFIFO : S_IFSOCK;\r
++                      init_special_inode(i, i->i_mode, 0);\r
++                      break;\r
++               }\r
++               default:\r
++                      ERROR("Unknown inode type %d in squashfs_iget!\n",\r
++                                      inodeb->inode_type);\r
++                      goto failed_read1;\r
++      }\r
++      \r
++      return 1;\r
++\r
++failed_read:\r
++      ERROR("Unable to read inode [%x:%x]\n", block, offset);\r
++\r
++failed_read1:\r
++      return 0;\r
++}\r
++\r
++\r
++static int get_dir_index_using_offset(struct super_block *s, long long \r
++                              *next_block, unsigned int *next_offset,\r
++                              long long index_start,\r
++                              unsigned int index_offset, int i_count,\r
++                              long long f_pos)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      int i, length = 0;\r
++      struct squashfs_dir_index_2 index;\r
++\r
++      TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",\r
++                                      i_count, (unsigned int) f_pos);\r
++\r
++      if (f_pos == 0)\r
++              goto finish;\r
++\r
++      for (i = 0; i < i_count; i++) {\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_index_2 sindex;\r
++                      squashfs_get_cached_block(s, (char *) &sindex,\r
++                                      index_start, index_offset,\r
++                                      sizeof(sindex), &index_start,\r
++                                      &index_offset);\r
++                      SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);\r
++              } else\r
++                      squashfs_get_cached_block(s, (char *) &index,\r
++                                      index_start, index_offset,\r
++                                      sizeof(index), &index_start,\r
++                                      &index_offset);\r
++\r
++              if (index.index > f_pos)\r
++                      break;\r
++\r
++              squashfs_get_cached_block(s, NULL, index_start, index_offset,\r
++                                      index.size + 1, &index_start,\r
++                                      &index_offset);\r
++\r
++              length = index.index;\r
++              *next_block = index.start_block + sblk->directory_table_start;\r
++      }\r
++\r
++      *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;\r
++\r
++finish:\r
++      return length;\r
++}\r
++\r
++\r
++static int get_dir_index_using_name(struct super_block *s, long long\r
++                              *next_block, unsigned int *next_offset,\r
++                              long long index_start,\r
++                              unsigned int index_offset, int i_count,\r
++                              const char *name, int size)\r
++{\r
++      struct squashfs_sb_info *msblk = s->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      int i, length = 0;\r
++      struct squashfs_dir_index_2 *index;\r
++      char *str;\r
++\r
++      TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);\r
++\r
++      if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +\r
++              (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate squashfs_dir_index\n");\r
++              goto failure;\r
++      }\r
++\r
++      index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1);\r
++      strncpy(str, name, size);\r
++      str[size] = '\0';\r
++\r
++      for (i = 0; i < i_count; i++) {\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_index_2 sindex;\r
++                      squashfs_get_cached_block(s, (char *) &sindex,\r
++                                      index_start, index_offset,\r
++                                      sizeof(sindex), &index_start,\r
++                                      &index_offset);\r
++                      SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);\r
++              } else\r
++                      squashfs_get_cached_block(s, (char *) index,\r
++                                      index_start, index_offset,\r
++                                      sizeof(struct squashfs_dir_index_2),\r
++                                      &index_start, &index_offset);\r
++\r
++              squashfs_get_cached_block(s, index->name, index_start,\r
++                                      index_offset, index->size + 1,\r
++                                      &index_start, &index_offset);\r
++\r
++              index->name[index->size + 1] = '\0';\r
++\r
++              if (strcmp(index->name, str) > 0)\r
++                      break;\r
++\r
++              length = index->index;\r
++              *next_block = index->start_block + sblk->directory_table_start;\r
++      }\r
++\r
++      *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;\r
++      kfree(str);\r
++failure:\r
++      return length;\r
++}\r
++\r
++              \r
++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)\r
++{\r
++      struct inode *i = file->f_dentry->d_inode;\r
++      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      long long next_block = SQUASHFS_I(i)->start_block +\r
++              sblk->directory_table_start;\r
++      int next_offset = SQUASHFS_I(i)->offset, length = 0,\r
++              dir_count;\r
++      struct squashfs_dir_header_2 dirh;\r
++      struct squashfs_dir_entry_2 *dire;\r
++\r
++      TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);\r
++\r
++      if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +\r
++              SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate squashfs_dir_entry\n");\r
++              goto finish;\r
++      }\r
++\r
++      length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_start,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_count,\r
++                              file->f_pos);\r
++\r
++      while (length < i_size_read(i)) {\r
++              /* read directory header */\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_header_2 sdirh;\r
++                      \r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,\r
++                                      next_block, next_offset, sizeof(sdirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(sdirh);\r
++                      SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);\r
++              } else {\r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,\r
++                                      next_block, next_offset, sizeof(dirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(dirh);\r
++              }\r
++\r
++              dir_count = dirh.count + 1;\r
++              while (dir_count--) {\r
++                      if (msblk->swap) {\r
++                              struct squashfs_dir_entry_2 sdire;\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              &sdire, next_block, next_offset,\r
++                                              sizeof(sdire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              \r
++                              length += sizeof(sdire);\r
++                              SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);\r
++                      } else {\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              dire, next_block, next_offset,\r
++                                              sizeof(*dire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                              length += sizeof(*dire);\r
++                      }\r
++\r
++                      if (!squashfs_get_cached_block(i->i_sb, dire->name,\r
++                                              next_block, next_offset,\r
++                                              dire->size + 1, &next_block,\r
++                                              &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += dire->size + 1;\r
++\r
++                      if (file->f_pos >= length)\r
++                              continue;\r
++\r
++                      dire->name[dire->size + 1] = '\0';\r
++\r
++                      TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",\r
++                                      (unsigned int) dirent, dire->name,\r
++                                      dire->size + 1, (int) file->f_pos,\r
++                                      dirh.start_block, dire->offset,\r
++                                      squashfs_filetype_table[dire->type]);\r
++\r
++                      if (filldir(dirent, dire->name, dire->size + 1,\r
++                                      file->f_pos, SQUASHFS_MK_VFS_INODE(\r
++                                      dirh.start_block, dire->offset),\r
++                                      squashfs_filetype_table[dire->type])\r
++                                      < 0) {\r
++                              TRACE("Filldir returned less than 0\n");\r
++                              goto finish;\r
++                      }\r
++                      file->f_pos = length;\r
++              }\r
++      }\r
++\r
++finish:\r
++      kfree(dire);\r
++      return 0;\r
++\r
++failed_read:\r
++      ERROR("Unable to read directory block [%llx:%x]\n", next_block,\r
++              next_offset);\r
++      kfree(dire);\r
++      return 0;\r
++}\r
++\r
++\r
++static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,\r
++                              struct nameidata *nd)\r
++{\r
++      const unsigned char *name = dentry->d_name.name;\r
++      int len = dentry->d_name.len;\r
++      struct inode *inode = NULL;\r
++      struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++      long long next_block = SQUASHFS_I(i)->start_block +\r
++                              sblk->directory_table_start;\r
++      int next_offset = SQUASHFS_I(i)->offset, length = 0,\r
++                              dir_count;\r
++      struct squashfs_dir_header_2 dirh;\r
++      struct squashfs_dir_entry_2 *dire;\r
++      int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;\r
++\r
++      TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset);\r
++\r
++      if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +\r
++              SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {\r
++              ERROR("Failed to allocate squashfs_dir_entry\n");\r
++              goto exit_loop;\r
++      }\r
++\r
++      if (len > SQUASHFS_NAME_LEN)\r
++              goto exit_loop;\r
++\r
++      length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_start,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_offset,\r
++                              SQUASHFS_I(i)->u.s2.directory_index_count, name,\r
++                              len);\r
++\r
++      while (length < i_size_read(i)) {\r
++              /* read directory header */\r
++              if (msblk->swap) {\r
++                      struct squashfs_dir_header_2 sdirh;\r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,\r
++                                      next_block, next_offset, sizeof(sdirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(sdirh);\r
++                      SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);\r
++              } else {\r
++                      if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,\r
++                                      next_block, next_offset, sizeof(dirh),\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += sizeof(dirh);\r
++              }\r
++\r
++              dir_count = dirh.count + 1;\r
++              while (dir_count--) {\r
++                      if (msblk->swap) {\r
++                              struct squashfs_dir_entry_2 sdire;\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              &sdire, next_block,next_offset,\r
++                                              sizeof(sdire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++                              \r
++                              length += sizeof(sdire);\r
++                              SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);\r
++                      } else {\r
++                              if (!squashfs_get_cached_block(i->i_sb, (char *)\r
++                                              dire, next_block,next_offset,\r
++                                              sizeof(*dire), &next_block,\r
++                                              &next_offset))\r
++                                      goto failed_read;\r
++\r
++                              length += sizeof(*dire);\r
++                      }\r
++\r
++                      if (!squashfs_get_cached_block(i->i_sb, dire->name,\r
++                                      next_block, next_offset, dire->size + 1,\r
++                                      &next_block, &next_offset))\r
++                              goto failed_read;\r
++\r
++                      length += dire->size + 1;\r
++\r
++                      if (sorted && name[0] < dire->name[0])\r
++                              goto exit_loop;\r
++\r
++                      if ((len == dire->size + 1) && !strncmp(name,\r
++                                              dire->name, len)) {\r
++                              squashfs_inode_t ino =\r
++                                      SQUASHFS_MKINODE(dirh.start_block,\r
++                                      dire->offset);\r
++                              unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block,\r
++                                      dire->offset);\r
++\r
++                              TRACE("calling squashfs_iget for directory "\r
++                                      "entry %s, inode %x:%x, %lld\n", name,\r
++                                      dirh.start_block, dire->offset, ino);\r
++\r
++                              inode = squashfs_iget(i->i_sb, ino, inode_number);\r
++\r
++                              goto exit_loop;\r
++                      }\r
++              }\r
++      }\r
++\r
++exit_loop:\r
++      kfree(dire);\r
++      d_add(dentry, inode);\r
++      return ERR_PTR(0);\r
++\r
++failed_read:\r
++      ERROR("Unable to read directory block [%llx:%x]\n", next_block,\r
++              next_offset);\r
++      goto exit_loop;\r
++}\r
++\r
++\r
++int squashfs_2_0_supported(struct squashfs_sb_info *msblk)\r
++{\r
++      struct squashfs_super_block *sblk = &msblk->sblk;\r
++\r
++      msblk->read_inode = squashfs_read_inode_2;\r
++      msblk->read_fragment_index_table = read_fragment_index_table_2;\r
++\r
++      sblk->bytes_used = sblk->bytes_used_2;\r
++      sblk->uid_start = sblk->uid_start_2;\r
++      sblk->guid_start = sblk->guid_start_2;\r
++      sblk->inode_table_start = sblk->inode_table_start_2;\r
++      sblk->directory_table_start = sblk->directory_table_start_2;\r
++      sblk->fragment_table_start = sblk->fragment_table_start_2;\r
++\r
++      return 1;\r
++}\r
+diff -urN linux-2.6.23/fs/squashfs/uncomp.c linux-2.6.23.sqlzma/fs/squashfs/uncomp.c\r
+--- linux-2.6.23/fs/squashfs/uncomp.c  1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/fs/squashfs/uncomp.c   2007-10-14 12:43:55.000000000 -0400\r
+@@ -0,0 +1,221 @@\r
++/*\r
++ * Copyright (C) 2006, 2007 Junjiro Okajima\r
++ * Copyright (C) 2006, 2007 Tomas Matejicek, slax.org\r
++ *\r
++ * LICENSE follows the described one in lzma.txt.\r
++ */\r
++\r
++/* $Id: uncomp.c,v 1.30 2007/03/04 12:45:53 jro Exp $ */\r
++\r
++/* extract some parts from lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c */\r
++\r
++#ifndef __KERNEL__\r
++#include <stdio.h>\r
++#include <stdlib.h>\r
++#include <string.h>\r
++#include <errno.h>\r
++#include <assert.h>\r
++#include <pthread.h>\r
++#define unlikely(x)           __builtin_expect(!!(x), 0)\r
++#define BUG_ON(x)             assert(!(x))\r
++/* sqlzma buffers are always larger than a page. true? */\r
++#define kmalloc(sz,gfp)               malloc(sz)\r
++#define kfree(p)              free(p)\r
++#define zlib_inflate(s, f)    inflate(s, f)\r
++#define zlib_inflateInit(s)   inflateInit(s)\r
++#define zlib_inflateReset(s)  inflateReset(s)\r
++#define zlib_inflateEnd(s)    inflateEnd(s)\r
++#else\r
++#include <linux/init.h>\r
++#include <linux/module.h>\r
++#include <linux/kernel.h>\r
++#include <linux/vmalloc.h>\r
++#ifndef WARN_ON_ONCE\r
++#define WARN_ON_ONCE(b)       WARN_ON(b)\r
++#endif\r
++#endif /* __KERNEL__ */\r
++\r
++#include "sqlzma.h"\r
++#include "LzmaDecode.h"\r
++\r
++static int LzmaUncompress(struct sqlzma_un *un)\r
++{\r
++      int err, i, ret;\r
++      SizeT outSize, inProcessed, outProcessed, srclen;\r
++      /* it's about 24-80 bytes structure, if int is 32-bit */\r
++      CLzmaDecoderState state;\r
++      unsigned char *dst, *src, a[8];\r
++      struct sized_buf *sbuf;\r
++\r
++      /* Decode LZMA properties and allocate memory */\r
++      err = -EINVAL;\r
++      src = (unsigned char *)un->un_cmbuf;\r
++      ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE);\r
++      src += LZMA_PROPERTIES_SIZE;\r
++      if (unlikely(ret != LZMA_RESULT_OK))\r
++              goto out;\r
++      i = LzmaGetNumProbs(&state.Properties);\r
++      if (unlikely(i <= 0))\r
++              i = 1;\r
++      i *= sizeof(CProb);\r
++      sbuf = un->un_a + SQUN_PROB;\r
++      if (unlikely(sbuf->sz < i)) {\r
++              if (sbuf->buf && sbuf->buf != un->un_prob)\r
++                      kfree(sbuf->buf);\r
++#ifdef __KERNEL__\r
++              printk("%s:%d: %d --> %d\n", __func__, __LINE__, sbuf->sz, i);\r
++#else\r
++              printf("%d --> %d\n", sbuf->sz, i);\r
++#endif\r
++              err = -ENOMEM;\r
++              sbuf->sz = 0;\r
++              sbuf->buf = kmalloc(i, GFP_ATOMIC);\r
++              if (unlikely(!sbuf->buf))\r
++                      goto out;\r
++              sbuf->sz = i;\r
++      }\r
++      state.Probs = (void*)sbuf->buf;\r
++\r
++      /* Read uncompressed size */\r
++      memcpy(a, src, sizeof(a));\r
++      src += sizeof(a);\r
++      outSize = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24);\r
++\r
++      err = -EINVAL;\r
++      dst = un->un_resbuf;\r
++      if (unlikely(!dst || outSize > un->un_reslen))\r
++              goto out;\r
++      un->un_reslen = outSize;\r
++      srclen = un->un_cmlen - (src - un->un_cmbuf);\r
++\r
++      /* Decompress */\r
++      err = LzmaDecode(&state, src, srclen, &inProcessed, dst, outSize,\r
++                       &outProcessed);\r
++      if (err)\r
++              err = -EINVAL;\r
++\r
++ out:\r
++#ifndef __KERNEL__\r
++      if (err)\r
++              fprintf(stderr, "err %d\n", err);\r
++#endif\r
++      return err;\r
++}\r
++\r
++int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src,\r
++            struct sized_buf *dst)\r
++{\r
++      int err, by_lzma = 0;\r
++      if (un->un_lzma && is_lzma(*src->buf)) {\r
++              by_lzma = 1;\r
++              un->un_cmbuf = src->buf;\r
++              un->un_cmlen = src->sz;\r
++              un->un_resbuf = dst->buf;\r
++              un->un_reslen = dst->sz;\r
++\r
++              /* this library is thread-safe */\r
++              err = LzmaUncompress(un);\r
++              goto out;\r
++      }\r
++\r
++      err = zlib_inflateReset(&un->un_stream);\r
++      if (unlikely(err != Z_OK))\r
++              goto out;\r
++      un->un_stream.next_in = src->buf;\r
++      un->un_stream.avail_in = src->sz;\r
++      un->un_stream.next_out = dst->buf;\r
++      un->un_stream.avail_out = dst->sz;\r
++      err = zlib_inflate(&un->un_stream, Z_FINISH);\r
++      if (err == Z_STREAM_END)\r
++              err = 0;\r
++\r
++ out:\r
++      if (err) {\r
++#ifdef __KERNEL__\r
++              WARN_ON_ONCE(1);\r
++#else\r
++              char a[64] = "ZLIB ";\r
++              if (by_lzma) {\r
++                      strcpy(a, "LZMA ");\r
++#ifdef _REENTRANT\r
++                      strerror_r(err, a + 5, sizeof(a) - 5);\r
++#else\r
++                      strncat(a, strerror(err), sizeof(a) - 5);\r
++#endif\r
++              } else\r
++                      strncat(a, zError(err), sizeof(a) - 5);\r
++              fprintf(stderr, "%s: %.*s\n", __func__, sizeof(a), a);\r
++#endif\r
++      }\r
++      return err;\r
++}\r
++\r
++int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz)\r
++{\r
++      int err;\r
++\r
++      err = -ENOMEM;\r
++      un->un_lzma = do_lzma;\r
++      memset(un->un_a, 0, sizeof(un->un_a));\r
++      un->un_a[SQUN_PROB].buf = un->un_prob;\r
++      un->un_a[SQUN_PROB].sz = sizeof(un->un_prob);\r
++      if (res_sz) {\r
++              un->un_a[SQUN_RESULT].buf = kmalloc(res_sz, GFP_KERNEL);\r
++              if (unlikely(!un->un_a[SQUN_RESULT].buf))\r
++                      return err;\r
++              un->un_a[SQUN_RESULT].sz = res_sz;\r
++      }\r
++\r
++      un->un_stream.next_in = NULL;\r
++      un->un_stream.avail_in = 0;\r
++#ifdef __KERNEL__\r
++      un->un_stream.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);\r
++      if (unlikely(!un->un_stream.workspace))\r
++              return err;\r
++#else\r
++      un->un_stream.opaque = NULL;\r
++      un->un_stream.zalloc = Z_NULL;\r
++      un->un_stream.zfree = Z_NULL;\r
++#endif\r
++      err = zlib_inflateInit(&un->un_stream);\r
++      if (unlikely(err == Z_MEM_ERROR))\r
++              return -ENOMEM;\r
++      BUG_ON(err);\r
++      return err;\r
++}\r
++\r
++void sqlzma_fin(struct sqlzma_un *un)\r
++{\r
++      int i;\r
++      for (i = 0; i < SQUN_LAST; i++)\r
++              if (un->un_a[i].buf && un->un_a[i].buf != un->un_prob)\r
++                      kfree(un->un_a[i].buf);\r
++      BUG_ON(zlib_inflateEnd(&un->un_stream) != Z_OK);\r
++}\r
++\r
++#ifdef __KERNEL__\r
++EXPORT_SYMBOL(sqlzma_un);\r
++EXPORT_SYMBOL(sqlzma_init);\r
++EXPORT_SYMBOL(sqlzma_fin);\r
++\r
++#if 0\r
++static int __init sqlzma_init(void)\r
++{\r
++      return 0;\r
++}\r
++\r
++static void __exit sqlzma_exit(void)\r
++{\r
++}\r
++\r
++module_init(sqlzma_init);\r
++module_exit(sqlzma_exit);\r
++#endif\r
++\r
++MODULE_LICENSE("GPL");\r
++MODULE_AUTHOR("Junjiro Okajima <hooanon05 at yahoo dot co dot jp>");\r
++MODULE_VERSION("$Id: uncomp.c,v 1.30 2007/03/04 12:45:53 jro Exp $");\r
++MODULE_DESCRIPTION("LZMA uncompress for squashfs. "\r
++                 "Some functions for squashfs to support LZMA and "\r
++                 "a tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org.");\r
++#endif\r
+diff -urN linux-2.6.23/include/linux/squashfs_fs.h linux-2.6.23.sqlzma/include/linux/squashfs_fs.h\r
+--- linux-2.6.23/include/linux/squashfs_fs.h   1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/include/linux/squashfs_fs.h    2007-10-14 10:24:31.000000000 -0400\r
+@@ -0,0 +1,934 @@\r
++#ifndef SQUASHFS_FS\r
++#define SQUASHFS_FS\r
++\r
++/*\r
++ * Squashfs\r
++ *\r
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
++ * Phillip Lougher <phillip@lougher.org.uk>\r
++ *\r
++ * This program is free software; you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License\r
++ * as published by the Free Software Foundation; either version 2,\r
++ * or (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program; if not, write to the Free Software\r
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
++ *\r
++ * squashfs_fs.h\r
++ */\r
++\r
++#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY\r
++#define CONFIG_SQUASHFS_2_0_COMPATIBILITY\r
++#endif\r
++\r
++#ifdef        CONFIG_SQUASHFS_VMALLOC\r
++#define SQUASHFS_ALLOC(a)             vmalloc(a)\r
++#define SQUASHFS_FREE(a)              vfree(a)\r
++#else\r
++#define SQUASHFS_ALLOC(a)             kmalloc(a, GFP_KERNEL)\r
++#define SQUASHFS_FREE(a)              kfree(a)\r
++#endif\r
++#define SQUASHFS_CACHED_FRAGMENTS     CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE     \r
++#define SQUASHFS_MAJOR                        3\r
++#define SQUASHFS_MINOR                        0\r
++#define SQUASHFS_MAGIC                        0x73717368\r
++#define SQUASHFS_MAGIC_SWAP           0x68737173\r
++#define SQUASHFS_START                        0\r
++\r
++/* size of metadata (inode and directory) blocks */\r
++#define SQUASHFS_METADATA_SIZE                8192\r
++#define SQUASHFS_METADATA_LOG         13\r
++\r
++/* default size of data blocks */\r
++#define SQUASHFS_FILE_SIZE            65536\r
++#define SQUASHFS_FILE_LOG             16\r
++\r
++#define SQUASHFS_FILE_MAX_SIZE                65536\r
++\r
++/* Max number of uids and gids */\r
++#define SQUASHFS_UIDS                 256\r
++#define SQUASHFS_GUIDS                        255\r
++\r
++/* Max length of filename (not 255) */\r
++#define SQUASHFS_NAME_LEN             256\r
++\r
++#define SQUASHFS_INVALID              ((long long) 0xffffffffffff)\r
++#define SQUASHFS_INVALID_FRAG         ((unsigned int) 0xffffffff)\r
++#define SQUASHFS_INVALID_BLK          ((long long) -1)\r
++#define SQUASHFS_USED_BLK             ((long long) -2)\r
++\r
++/* Filesystem flags */\r
++#define SQUASHFS_NOI                  0\r
++#define SQUASHFS_NOD                  1\r
++#define SQUASHFS_CHECK                        2\r
++#define SQUASHFS_NOF                  3\r
++#define SQUASHFS_NO_FRAG              4\r
++#define SQUASHFS_ALWAYS_FRAG          5\r
++#define SQUASHFS_DUPLICATE            6\r
++#define SQUASHFS_EXPORT                       7\r
++\r
++#define SQUASHFS_BIT(flag, bit)               ((flag >> bit) & 1)\r
++\r
++#define SQUASHFS_UNCOMPRESSED_INODES(flags)   SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_NOI)\r
++\r
++#define SQUASHFS_UNCOMPRESSED_DATA(flags)     SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_NOD)\r
++\r
++#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags)        SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_NOF)\r
++\r
++#define SQUASHFS_NO_FRAGMENTS(flags)          SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_NO_FRAG)\r
++\r
++#define SQUASHFS_ALWAYS_FRAGMENTS(flags)      SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_ALWAYS_FRAG)\r
++\r
++#define SQUASHFS_DUPLICATES(flags)            SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_DUPLICATE)\r
++\r
++#define SQUASHFS_EXPORTABLE(flags)            SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_EXPORT)\r
++\r
++#define SQUASHFS_CHECK_DATA(flags)            SQUASHFS_BIT(flags, \\r
++                                              SQUASHFS_CHECK)\r
++\r
++#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \\r
++              duplicate_checking, exortable)  (noi | (nod << 1) | (check_data << 2) \\r
++              | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \\r
++              (duplicate_checking << 6) | (exportable << 7))\r
++\r
++/* Max number of types and file types */\r
++#define SQUASHFS_DIR_TYPE             1\r
++#define SQUASHFS_FILE_TYPE            2\r
++#define SQUASHFS_SYMLINK_TYPE         3\r
++#define SQUASHFS_BLKDEV_TYPE          4\r
++#define SQUASHFS_CHRDEV_TYPE          5\r
++#define SQUASHFS_FIFO_TYPE            6\r
++#define SQUASHFS_SOCKET_TYPE          7\r
++#define SQUASHFS_LDIR_TYPE            8\r
++#define SQUASHFS_LREG_TYPE            9\r
++\r
++/* 1.0 filesystem type definitions */\r
++#define SQUASHFS_TYPES                        5\r
++#define SQUASHFS_IPC_TYPE             0\r
++\r
++/* Flag whether block is compressed or uncompressed, bit is set if block is\r
++ * uncompressed */\r
++#define SQUASHFS_COMPRESSED_BIT               (1 << 15)\r
++\r
++#define SQUASHFS_COMPRESSED_SIZE(B)   (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \\r
++              (B) & ~SQUASHFS_COMPRESSED_BIT :  SQUASHFS_COMPRESSED_BIT)\r
++\r
++#define SQUASHFS_COMPRESSED(B)                (!((B) & SQUASHFS_COMPRESSED_BIT))\r
++\r
++#define SQUASHFS_COMPRESSED_BIT_BLOCK         (1 << 24)\r
++\r
++#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B)     (((B) & \\r
++      ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \\r
++      ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)\r
++\r
++#define SQUASHFS_COMPRESSED_BLOCK(B)  (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))\r
++\r
++/*\r
++ * Inode number ops.  Inodes consist of a compressed block number, and an\r
++ * uncompressed  offset within that block\r
++ */\r
++#define SQUASHFS_INODE_BLK(a)         ((unsigned int) ((a) >> 16))\r
++\r
++#define SQUASHFS_INODE_OFFSET(a)      ((unsigned int) ((a) & 0xffff))\r
++\r
++#define SQUASHFS_MKINODE(A, B)                ((squashfs_inode_t)(((squashfs_inode_t) (A)\\r
++                                      << 16) + (B)))\r
++\r
++/* Compute 32 bit VFS inode number from squashfs inode number */\r
++#define SQUASHFS_MK_VFS_INODE(a, b)   ((unsigned int) (((a) << 8) + \\r
++                                      ((b) >> 2) + 1))\r
++/* XXX */\r
++\r
++/* Translate between VFS mode and squashfs mode */\r
++#define SQUASHFS_MODE(a)              ((a) & 0xfff)\r
++\r
++/* fragment and fragment table defines */\r
++#define SQUASHFS_FRAGMENT_BYTES(A)    ((A) * sizeof(struct squashfs_fragment_entry))\r
++\r
++#define SQUASHFS_FRAGMENT_INDEX(A)    (SQUASHFS_FRAGMENT_BYTES(A) / \\r
++                                      SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A)     (SQUASHFS_FRAGMENT_BYTES(A) % \\r
++                                              SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_FRAGMENT_INDEXES(A)  ((SQUASHFS_FRAGMENT_BYTES(A) + \\r
++                                      SQUASHFS_METADATA_SIZE - 1) / \\r
++                                      SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_FRAGMENT_INDEX_BYTES(A)      (SQUASHFS_FRAGMENT_INDEXES(A) *\\r
++                                              sizeof(long long))\r
++\r
++/* inode lookup table defines */\r
++#define SQUASHFS_LOOKUP_BYTES(A)      ((A) * sizeof(squashfs_inode_t))\r
++\r
++#define SQUASHFS_LOOKUP_BLOCK(A)              (SQUASHFS_LOOKUP_BYTES(A) / \\r
++                                              SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A)               (SQUASHFS_LOOKUP_BYTES(A) % \\r
++                                              SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_LOOKUP_BLOCKS(A)     ((SQUASHFS_LOOKUP_BYTES(A) + \\r
++                                      SQUASHFS_METADATA_SIZE - 1) / \\r
++                                      SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_LOOKUP_BLOCK_BYTES(A)        (SQUASHFS_LOOKUP_BLOCKS(A) *\\r
++                                      sizeof(long long))\r
++\r
++/* cached data constants for filesystem */\r
++#define SQUASHFS_CACHED_BLKS          8\r
++\r
++#define SQUASHFS_MAX_FILE_SIZE_LOG    64\r
++\r
++#define SQUASHFS_MAX_FILE_SIZE                ((long long) 1 << \\r
++                                      (SQUASHFS_MAX_FILE_SIZE_LOG - 2))\r
++\r
++#define SQUASHFS_MARKER_BYTE          0xff\r
++\r
++/* meta index cache */\r
++#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))\r
++#define SQUASHFS_META_ENTRIES 31\r
++#define SQUASHFS_META_NUMBER  8\r
++#define SQUASHFS_SLOTS                4\r
++\r
++struct meta_entry {\r
++      long long               data_block;\r
++      unsigned int            index_block;\r
++      unsigned short          offset;\r
++      unsigned short          pad;\r
++};\r
++\r
++struct meta_index {\r
++      unsigned int            inode_number;\r
++      unsigned int            offset;\r
++      unsigned short          entries;\r
++      unsigned short          skip;\r
++      unsigned short          locked;\r
++      unsigned short          pad;\r
++      struct meta_entry       meta_entry[SQUASHFS_META_ENTRIES];\r
++};\r
++\r
++\r
++/*\r
++ * definitions for structures on disk\r
++ */\r
++\r
++typedef long long             squashfs_block_t;\r
++typedef long long             squashfs_inode_t;\r
++\r
++struct squashfs_super_block {\r
++      unsigned int            s_magic;\r
++      unsigned int            inodes;\r
++      unsigned int            bytes_used_2;\r
++      unsigned int            uid_start_2;\r
++      unsigned int            guid_start_2;\r
++      unsigned int            inode_table_start_2;\r
++      unsigned int            directory_table_start_2;\r
++      unsigned int            s_major:16;\r
++      unsigned int            s_minor:16;\r
++      unsigned int            block_size_1:16;\r
++      unsigned int            block_log:16;\r
++      unsigned int            flags:8;\r
++      unsigned int            no_uids:8;\r
++      unsigned int            no_guids:8;\r
++      unsigned int            mkfs_time /* time of filesystem creation */;\r
++      squashfs_inode_t        root_inode;\r
++      unsigned int            block_size;\r
++      unsigned int            fragments;\r
++      unsigned int            fragment_table_start_2;\r
++      long long               bytes_used;\r
++      long long               uid_start;\r
++      long long               guid_start;\r
++      long long               inode_table_start;\r
++      long long               directory_table_start;\r
++      long long               fragment_table_start;\r
++      long long               lookup_table_start;\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dir_index {\r
++      unsigned int            index;\r
++      unsigned int            start_block;\r
++      unsigned char           size;\r
++      unsigned char           name[0];\r
++} __attribute__ ((packed));\r
++\r
++#define SQUASHFS_BASE_INODE_HEADER            \\r
++      unsigned int            inode_type:4;   \\r
++      unsigned int            mode:12;        \\r
++      unsigned int            uid:8;          \\r
++      unsigned int            guid:8;         \\r
++      unsigned int            mtime;          \\r
++      unsigned int            inode_number;\r
++\r
++struct squashfs_base_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_ipc_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      unsigned int            nlink;\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dev_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      unsigned int            nlink;\r
++      unsigned short          rdev;\r
++} __attribute__ ((packed));\r
++      \r
++struct squashfs_symlink_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      unsigned int            nlink;\r
++      unsigned short          symlink_size;\r
++      char                    symlink[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_reg_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      squashfs_block_t        start_block;\r
++      unsigned int            fragment;\r
++      unsigned int            offset;\r
++      unsigned int            file_size;\r
++      unsigned short          block_list[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_lreg_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      unsigned int            nlink;\r
++      squashfs_block_t        start_block;\r
++      unsigned int            fragment;\r
++      unsigned int            offset;\r
++      long long               file_size;\r
++      unsigned short          block_list[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dir_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      unsigned int            nlink;\r
++      unsigned int            file_size:19;\r
++      unsigned int            offset:13;\r
++      unsigned int            start_block;\r
++      unsigned int            parent_inode;\r
++} __attribute__  ((packed));\r
++\r
++struct squashfs_ldir_inode_header {\r
++      SQUASHFS_BASE_INODE_HEADER;\r
++      unsigned int            nlink;\r
++      unsigned int            file_size:27;\r
++      unsigned int            offset:13;\r
++      unsigned int            start_block;\r
++      unsigned int            i_count:16;\r
++      unsigned int            parent_inode;\r
++      struct squashfs_dir_index       index[0];\r
++} __attribute__  ((packed));\r
++\r
++union squashfs_inode_header {\r
++      struct squashfs_base_inode_header       base;\r
++      struct squashfs_dev_inode_header        dev;\r
++      struct squashfs_symlink_inode_header    symlink;\r
++      struct squashfs_reg_inode_header        reg;\r
++      struct squashfs_lreg_inode_header       lreg;\r
++      struct squashfs_dir_inode_header        dir;\r
++      struct squashfs_ldir_inode_header       ldir;\r
++      struct squashfs_ipc_inode_header        ipc;\r
++};\r
++      \r
++struct squashfs_dir_entry {\r
++      unsigned int            offset:13;\r
++      unsigned int            type:3;\r
++      unsigned int            size:8;\r
++      int                     inode_number:16;\r
++      char                    name[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dir_header {\r
++      unsigned int            count:8;\r
++      unsigned int            start_block;\r
++      unsigned int            inode_number;\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_fragment_entry {\r
++      long long               start_block;\r
++      unsigned int            size;\r
++      unsigned int            pending;\r
++} __attribute__ ((packed));\r
++\r
++extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);\r
++extern int squashfs_uncompress_init(void);\r
++extern int squashfs_uncompress_exit(void);\r
++\r
++/*\r
++ * macros to convert each packed bitfield structure from little endian to big\r
++ * endian and vice versa.  These are needed when creating or using a filesystem\r
++ * on a machine with different byte ordering to the target architecture.\r
++ *\r
++ */\r
++\r
++#define SQUASHFS_SWAP_START \\r
++      int bits;\\r
++      int b_pos;\\r
++      unsigned long long val;\\r
++      unsigned char *s;\\r
++      unsigned char *d;\r
++\r
++#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\\r
++      SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\\r
++      SQUASHFS_SWAP((s)->inodes, d, 32, 32);\\r
++      SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\\r
++      SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\\r
++      SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\\r
++      SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\\r
++      SQUASHFS_SWAP((s)->s_major, d, 224, 16);\\r
++      SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\\r
++      SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\\r
++      SQUASHFS_SWAP((s)->block_log, d, 272, 16);\\r
++      SQUASHFS_SWAP((s)->flags, d, 288, 8);\\r
++      SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\\r
++      SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\\r
++      SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\\r
++      SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\\r
++      SQUASHFS_SWAP((s)->block_size, d, 408, 32);\\r
++      SQUASHFS_SWAP((s)->fragments, d, 440, 32);\\r
++      SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\\r
++      SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\\r
++      SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\\r
++      SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\\r
++      SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\\r
++      SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\\r
++      SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\\r
++      SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\\r
++      SQUASHFS_MEMSET(s, d, n);\\r
++      SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\\r
++      SQUASHFS_SWAP((s)->mode, d, 4, 12);\\r
++      SQUASHFS_SWAP((s)->uid, d, 16, 8);\\r
++      SQUASHFS_SWAP((s)->guid, d, 24, 8);\\r
++      SQUASHFS_SWAP((s)->mtime, d, 32, 32);\\r
++      SQUASHFS_SWAP((s)->inode_number, d, 64, 32);\r
++\r
++#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\\r
++}\r
++\r
++#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_ipc_inode_header))\\r
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_dev_inode_header)); \\r
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->rdev, d, 128, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_symlink_inode_header));\\r
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_reg_inode_header));\\r
++      SQUASHFS_SWAP((s)->start_block, d, 96, 64);\\r
++      SQUASHFS_SWAP((s)->fragment, d, 160, 32);\\r
++      SQUASHFS_SWAP((s)->offset, d, 192, 32);\\r
++      SQUASHFS_SWAP((s)->file_size, d, 224, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_lreg_inode_header));\\r
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 128, 64);\\r
++      SQUASHFS_SWAP((s)->fragment, d, 192, 32);\\r
++      SQUASHFS_SWAP((s)->offset, d, 224, 32);\\r
++      SQUASHFS_SWAP((s)->file_size, d, 256, 64);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_dir_inode_header));\\r
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->file_size, d, 128, 19);\\r
++      SQUASHFS_SWAP((s)->offset, d, 147, 13);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 160, 32);\\r
++      SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
++                      sizeof(struct squashfs_ldir_inode_header));\\r
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->file_size, d, 128, 27);\\r
++      SQUASHFS_SWAP((s)->offset, d, 155, 13);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 168, 32);\\r
++      SQUASHFS_SWAP((s)->i_count, d, 200, 16);\\r
++      SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\\r
++      SQUASHFS_SWAP((s)->index, d, 0, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 32, 32);\\r
++      SQUASHFS_SWAP((s)->size, d, 64, 8);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\\r
++      SQUASHFS_SWAP((s)->count, d, 0, 8);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 8, 32);\\r
++      SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\\r
++      SQUASHFS_SWAP((s)->offset, d, 0, 13);\\r
++      SQUASHFS_SWAP((s)->type, d, 13, 3);\\r
++      SQUASHFS_SWAP((s)->size, d, 16, 8);\\r
++      SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\\r
++      SQUASHFS_SWAP((s)->start_block, d, 0, 64);\\r
++      SQUASHFS_SWAP((s)->size, d, 64, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1)\r
++\r
++#define SQUASHFS_SWAP_SHORTS(s, d, n) {\\r
++      int entry;\\r
++      int bit_position;\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, n * 2);\\r
++      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\r
++                      16)\\r
++              SQUASHFS_SWAP(s[entry], d, bit_position, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_INTS(s, d, n) {\\r
++      int entry;\\r
++      int bit_position;\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, n * 4);\\r
++      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\r
++                      32)\\r
++              SQUASHFS_SWAP(s[entry], d, bit_position, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\\r
++      int entry;\\r
++      int bit_position;\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, n * 8);\\r
++      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\r
++                      64)\\r
++              SQUASHFS_SWAP(s[entry], d, bit_position, 64);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\\r
++      int entry;\\r
++      int bit_position;\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, n * bits / 8);\\r
++      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\r
++                      bits)\\r
++              SQUASHFS_SWAP(s[entry], d, bit_position, bits);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)\r
++#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)\r
++\r
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY\r
++\r
++struct squashfs_base_inode_header_1 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:4; /* index into uid table */\r
++      unsigned int            guid:4; /* index into guid table */\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_ipc_inode_header_1 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:4; /* index into uid table */\r
++      unsigned int            guid:4; /* index into guid table */\r
++      unsigned int            type:4;\r
++      unsigned int            offset:4;\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dev_inode_header_1 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:4; /* index into uid table */\r
++      unsigned int            guid:4; /* index into guid table */\r
++      unsigned short          rdev;\r
++} __attribute__ ((packed));\r
++      \r
++struct squashfs_symlink_inode_header_1 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:4; /* index into uid table */\r
++      unsigned int            guid:4; /* index into guid table */\r
++      unsigned short          symlink_size;\r
++      char                    symlink[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_reg_inode_header_1 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:4; /* index into uid table */\r
++      unsigned int            guid:4; /* index into guid table */\r
++      unsigned int            mtime;\r
++      unsigned int            start_block;\r
++      unsigned int            file_size:32;\r
++      unsigned short          block_list[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dir_inode_header_1 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:4; /* index into uid table */\r
++      unsigned int            guid:4; /* index into guid table */\r
++      unsigned int            file_size:19;\r
++      unsigned int            offset:13;\r
++      unsigned int            mtime;\r
++      unsigned int            start_block:24;\r
++} __attribute__  ((packed));\r
++\r
++#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \\r
++      SQUASHFS_MEMSET(s, d, n);\\r
++      SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\\r
++      SQUASHFS_SWAP((s)->mode, d, 4, 12);\\r
++      SQUASHFS_SWAP((s)->uid, d, 16, 4);\\r
++      SQUASHFS_SWAP((s)->guid, d, 20, 4);\r
++\r
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\\r
++}\r
++\r
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
++                      sizeof(struct squashfs_ipc_inode_header_1));\\r
++      SQUASHFS_SWAP((s)->type, d, 24, 4);\\r
++      SQUASHFS_SWAP((s)->offset, d, 28, 4);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
++                      sizeof(struct squashfs_dev_inode_header_1));\\r
++      SQUASHFS_SWAP((s)->rdev, d, 24, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
++                      sizeof(struct squashfs_symlink_inode_header_1));\\r
++      SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
++                      sizeof(struct squashfs_reg_inode_header_1));\\r
++      SQUASHFS_SWAP((s)->mtime, d, 24, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 56, 32);\\r
++      SQUASHFS_SWAP((s)->file_size, d, 88, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
++                      sizeof(struct squashfs_dir_inode_header_1));\\r
++      SQUASHFS_SWAP((s)->file_size, d, 24, 19);\\r
++      SQUASHFS_SWAP((s)->offset, d, 43, 13);\\r
++      SQUASHFS_SWAP((s)->mtime, d, 56, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 88, 24);\\r
++}\r
++\r
++#endif\r
++\r
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY\r
++\r
++struct squashfs_dir_index_2 {\r
++      unsigned int            index:27;\r
++      unsigned int            start_block:29;\r
++      unsigned char           size;\r
++      unsigned char           name[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_base_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_ipc_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dev_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++      unsigned short          rdev;\r
++} __attribute__ ((packed));\r
++      \r
++struct squashfs_symlink_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++      unsigned short          symlink_size;\r
++      char                    symlink[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_reg_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++      unsigned int            mtime;\r
++      unsigned int            start_block;\r
++      unsigned int            fragment;\r
++      unsigned int            offset;\r
++      unsigned int            file_size:32;\r
++      unsigned short          block_list[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dir_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++      unsigned int            file_size:19;\r
++      unsigned int            offset:13;\r
++      unsigned int            mtime;\r
++      unsigned int            start_block:24;\r
++} __attribute__  ((packed));\r
++\r
++struct squashfs_ldir_inode_header_2 {\r
++      unsigned int            inode_type:4;\r
++      unsigned int            mode:12; /* protection */\r
++      unsigned int            uid:8; /* index into uid table */\r
++      unsigned int            guid:8; /* index into guid table */\r
++      unsigned int            file_size:27;\r
++      unsigned int            offset:13;\r
++      unsigned int            mtime;\r
++      unsigned int            start_block:24;\r
++      unsigned int            i_count:16;\r
++      struct squashfs_dir_index_2     index[0];\r
++} __attribute__  ((packed));\r
++\r
++union squashfs_inode_header_2 {\r
++      struct squashfs_base_inode_header_2     base;\r
++      struct squashfs_dev_inode_header_2      dev;\r
++      struct squashfs_symlink_inode_header_2  symlink;\r
++      struct squashfs_reg_inode_header_2      reg;\r
++      struct squashfs_dir_inode_header_2      dir;\r
++      struct squashfs_ldir_inode_header_2     ldir;\r
++      struct squashfs_ipc_inode_header_2      ipc;\r
++};\r
++      \r
++struct squashfs_dir_header_2 {\r
++      unsigned int            count:8;\r
++      unsigned int            start_block:24;\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_dir_entry_2 {\r
++      unsigned int            offset:13;\r
++      unsigned int            type:3;\r
++      unsigned int            size:8;\r
++      char                    name[0];\r
++} __attribute__ ((packed));\r
++\r
++struct squashfs_fragment_entry_2 {\r
++      unsigned int            start_block;\r
++      unsigned int            size;\r
++} __attribute__ ((packed));\r
++\r
++#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\\r
++      SQUASHFS_MEMSET(s, d, n);\\r
++      SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\\r
++      SQUASHFS_SWAP((s)->mode, d, 4, 12);\\r
++      SQUASHFS_SWAP((s)->uid, d, 16, 8);\\r
++      SQUASHFS_SWAP((s)->guid, d, 24, 8);\\r
++\r
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\\r
++}\r
++\r
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \\r
++      SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))\r
++\r
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
++                      sizeof(struct squashfs_dev_inode_header_2)); \\r
++      SQUASHFS_SWAP((s)->rdev, d, 32, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
++                      sizeof(struct squashfs_symlink_inode_header_2));\\r
++      SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
++                      sizeof(struct squashfs_reg_inode_header_2));\\r
++      SQUASHFS_SWAP((s)->mtime, d, 32, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 64, 32);\\r
++      SQUASHFS_SWAP((s)->fragment, d, 96, 32);\\r
++      SQUASHFS_SWAP((s)->offset, d, 128, 32);\\r
++      SQUASHFS_SWAP((s)->file_size, d, 160, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
++                      sizeof(struct squashfs_dir_inode_header_2));\\r
++      SQUASHFS_SWAP((s)->file_size, d, 32, 19);\\r
++      SQUASHFS_SWAP((s)->offset, d, 51, 13);\\r
++      SQUASHFS_SWAP((s)->mtime, d, 64, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 96, 24);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
++                      sizeof(struct squashfs_ldir_inode_header_2));\\r
++      SQUASHFS_SWAP((s)->file_size, d, 32, 27);\\r
++      SQUASHFS_SWAP((s)->offset, d, 59, 13);\\r
++      SQUASHFS_SWAP((s)->mtime, d, 72, 32);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 104, 24);\\r
++      SQUASHFS_SWAP((s)->i_count, d, 128, 16);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\\r
++      SQUASHFS_SWAP((s)->index, d, 0, 27);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 27, 29);\\r
++      SQUASHFS_SWAP((s)->size, d, 56, 8);\\r
++}\r
++#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\\r
++      SQUASHFS_SWAP((s)->count, d, 0, 8);\\r
++      SQUASHFS_SWAP((s)->start_block, d, 8, 24);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\\r
++      SQUASHFS_SWAP((s)->offset, d, 0, 13);\\r
++      SQUASHFS_SWAP((s)->type, d, 13, 3);\\r
++      SQUASHFS_SWAP((s)->size, d, 16, 8);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\\r
++      SQUASHFS_SWAP_START\\r
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\\r
++      SQUASHFS_SWAP((s)->start_block, d, 0, 32);\\r
++      SQUASHFS_SWAP((s)->size, d, 32, 32);\\r
++}\r
++\r
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)\r
++\r
++/* fragment and fragment table defines */\r
++#define SQUASHFS_FRAGMENT_BYTES_2(A)  (A * sizeof(struct squashfs_fragment_entry_2))\r
++\r
++#define SQUASHFS_FRAGMENT_INDEX_2(A)  (SQUASHFS_FRAGMENT_BYTES_2(A) / \\r
++                                      SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A)   (SQUASHFS_FRAGMENT_BYTES_2(A) % \\r
++                                              SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_FRAGMENT_INDEXES_2(A)        ((SQUASHFS_FRAGMENT_BYTES_2(A) + \\r
++                                      SQUASHFS_METADATA_SIZE - 1) / \\r
++                                      SQUASHFS_METADATA_SIZE)\r
++\r
++#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A)    (SQUASHFS_FRAGMENT_INDEXES_2(A) *\\r
++                                              sizeof(int))\r
++\r
++#endif\r
++\r
++#ifdef __KERNEL__\r
++\r
++/*\r
++ * macros used to swap each structure entry, taking into account\r
++ * bitfields and different bitfield placing conventions on differing\r
++ * architectures\r
++ */\r
++\r
++#include <asm/byteorder.h>\r
++\r
++#ifdef __BIG_ENDIAN\r
++      /* convert from little endian to big endian */\r
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \\r
++              tbits, b_pos)\r
++#else\r
++      /* convert from big endian to little endian */ \r
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \\r
++              tbits, 64 - tbits - b_pos)\r
++#endif\r
++\r
++#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\\r
++      b_pos = pos % 8;\\r
++      val = 0;\\r
++      s = (unsigned char *)p + (pos / 8);\\r
++      d = ((unsigned char *) &val) + 7;\\r
++      for(bits = 0; bits < (tbits + b_pos); bits += 8) \\r
++              *d-- = *s++;\\r
++      value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\\r
++}\r
++\r
++#define SQUASHFS_MEMSET(s, d, n)      memset(s, 0, n);\r
++\r
++#endif\r
++#endif\r
+diff -urN linux-2.6.23/include/linux/squashfs_fs_i.h linux-2.6.23.sqlzma/include/linux/squashfs_fs_i.h\r
+--- linux-2.6.23/include/linux/squashfs_fs_i.h 1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/include/linux/squashfs_fs_i.h  2007-10-14 10:24:31.000000000 -0400\r
+@@ -0,0 +1,45 @@\r
++#ifndef SQUASHFS_FS_I\r
++#define SQUASHFS_FS_I\r
++/*\r
++ * Squashfs\r
++ *\r
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
++ * Phillip Lougher <phillip@lougher.org.uk>\r
++ *\r
++ * This program is free software; you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License\r
++ * as published by the Free Software Foundation; either version 2,\r
++ * or (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program; if not, write to the Free Software\r
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
++ *\r
++ * squashfs_fs_i.h\r
++ */\r
++\r
++struct squashfs_inode_info {\r
++      long long       start_block;\r
++      unsigned int    offset;\r
++      union {\r
++              struct {\r
++                      long long       fragment_start_block;\r
++                      unsigned int    fragment_size;\r
++                      unsigned int    fragment_offset;\r
++                      long long       block_list_start;\r
++              } s1;\r
++              struct {\r
++                      long long       directory_index_start;\r
++                      unsigned int    directory_index_offset;\r
++                      unsigned int    directory_index_count;\r
++                      unsigned int    parent_inode;\r
++              } s2;\r
++      } u;\r
++      struct inode    vfs_inode;\r
++};\r
++#endif\r
+diff -urN linux-2.6.23/include/linux/squashfs_fs_sb.h linux-2.6.23.sqlzma/include/linux/squashfs_fs_sb.h\r
+--- linux-2.6.23/include/linux/squashfs_fs_sb.h        1969-12-31 19:00:00.000000000 -0500\r
++++ linux-2.6.23.sqlzma/include/linux/squashfs_fs_sb.h 2007-10-14 14:32:50.000000000 -0400\r
+@@ -0,0 +1,73 @@\r
++#ifndef SQUASHFS_FS_SB\r
++#define SQUASHFS_FS_SB\r
++/*\r
++ * Squashfs\r
++ *\r
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
++ * Phillip Lougher <phillip@lougher.org.uk>\r
++ *\r
++ * This program is free software; you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License\r
++ * as published by the Free Software Foundation; either version 2,\r
++ * or (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program; if not, write to the Free Software\r
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
++ *\r
++ * squashfs_fs_sb.h\r
++ */\r
++\r
++#include <linux/squashfs_fs.h>\r
++\r
++struct squashfs_cache {\r
++      long long       block;\r
++      int             length;\r
++      long long       next_index;\r
++      char            *data;\r
++};\r
++\r
++struct squashfs_fragment_cache {\r
++      long long       block;\r
++      int             length;\r
++      unsigned int    locked;\r
++      char            *data;\r
++};\r
++\r
++struct squashfs_sb_info {\r
++      struct squashfs_super_block     sblk;\r
++      int                     devblksize;\r
++      int                     devblksize_log2;\r
++      int                     swap;\r
++      struct squashfs_cache   *block_cache;\r
++      struct squashfs_fragment_cache  *fragment;\r
++      int                     next_cache;\r
++      int                     next_fragment;\r
++      int                     next_meta_index;\r
++      unsigned int            *uid;\r
++      unsigned int            *guid;\r
++      long long               *fragment_index;\r
++      unsigned int            *fragment_index_2;\r
++      char                    *read_page;\r
++      //struct mutex          read_data_mutex;\r
++      struct mutex            read_page_mutex;\r
++      struct mutex            block_cache_mutex;\r
++      struct mutex            fragment_mutex;\r
++      struct mutex            meta_index_mutex;\r
++      wait_queue_head_t       waitq;\r
++      wait_queue_head_t       fragment_wait_queue;\r
++      struct meta_index       *meta_index;\r
++      long long               *inode_lookup_table;\r
++      int                     (*read_inode)(struct inode *i,  squashfs_inode_t \\r
++                              inode);\r
++      long long               (*read_blocklist)(struct inode *inode, int \\r
++                              index, int readahead_blks, char *block_list, \\r
++                              unsigned short **block_p, unsigned int *bsize);\r
++      int                     (*read_fragment_index_table)(struct super_block *s);\r
++};\r
++#endif\r
+diff -urN linux-2.6.23/init/do_mounts_rd.c linux-2.6.23.sqlzma/init/do_mounts_rd.c\r
+--- linux-2.6.23/init/do_mounts_rd.c   2007-10-09 16:31:38.000000000 -0400\r
++++ linux-2.6.23.sqlzma/init/do_mounts_rd.c    2007-10-14 10:24:31.000000000 -0400\r
+@@ -5,6 +5,7 @@\r
+ #include <linux/ext2_fs.h>\r
+ #include <linux/romfs_fs.h>\r
+ #include <linux/cramfs_fs.h>\r
++#include <linux/squashfs_fs.h>\r
+ #include <linux/initrd.h>\r
+ #include <linux/string.h>\r
\r
+@@ -39,6 +40,7 @@\r
+  * numbers could not be found.\r
+  *\r
+  * We currently check for the following magic numbers:\r
++ *      squashfs\r
+  *    minix\r
+  *    ext2\r
+  *    romfs\r
+@@ -53,6 +55,7 @@\r
+       struct ext2_super_block *ext2sb;\r
+       struct romfs_super_block *romfsb;\r
+       struct cramfs_super *cramfsb;\r
++      struct squashfs_super_block *squashfsb;\r
+       int nblocks = -1;\r
+       unsigned char *buf;\r
\r
+@@ -64,6 +67,7 @@\r
+       ext2sb = (struct ext2_super_block *) buf;\r
+       romfsb = (struct romfs_super_block *) buf;\r
+       cramfsb = (struct cramfs_super *) buf;\r
++      squashfsb = (struct squashfs_super_block *) buf;\r
+       memset(buf, 0xe5, size);\r
\r
+       /*\r
+@@ -101,6 +105,18 @@\r
+               goto done;\r
+       }\r
\r
++      /* squashfs is at block zero too */\r
++      if (squashfsb->s_magic == SQUASHFS_MAGIC) {\r
++              printk(KERN_NOTICE\r
++                     "RAMDISK: squashfs filesystem found at block %d\n",\r
++                     start_block);\r
++              if (squashfsb->s_major < 3)\r
++                      nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;\r
++              else\r
++                      nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;\r
++              goto done;\r
++      }\r
++\r
+       /*\r
+        * Read block 1 to test for minix and ext2 superblock\r
+        */\r
index eefe72f..0afc545 100644 (file)
@@ -5,10 +5,10 @@ DEFAULT_PREFERENCE = "-1"
 DEFAULT_PREFERENCE_mpc8313e-rdb = "1"
 DEFAULT_PREFERENCE_mpc8315e-rdb = "1"
 
-PR = "r6"
+PR = "r7"
 
 SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/linux-2.6.24.tar.bz2 \
-           http://kamikaze.waninkoko.info/patches/2.6.24/kamikaze1/broken-out/squashfs-lzma-2.6.24.patch;patch=1 \
+           file://squashfs-lzma-2.6.24.patch;patch=1 \
            file://powerpc-clockres.patch;patch=1 \
            file://defconfig"
 
index 438ff72..4d338a1 100644 (file)
@@ -12,10 +12,10 @@ DEFAULT_PREFERENCE_oxnas = "1"
 DEFAULT_PREFERENCE_hipox = "1"
 DEFAULT_PREFERENCE_cs-e9302 = "1"
 
-PR = "r26"
+PR = "r27"
 
 SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/linux-2.6.24.tar.bz2 \
-           http://kamikaze.waninkoko.info/patches/2.6.24/kamikaze1/broken-out/squashfs-lzma-2.6.24.patch;patch=1 \
+           file://squashfs-lzma-2.6.24.patch;patch=1 \
           file://time.h.patch;patch=1 \
            file://defconfig"