1 diff -urN linux-2.6.23/fs/Kconfig linux-2.6.23.sqlzma/fs/Kconfig
\r
2 --- linux-2.6.23/fs/Kconfig 2007-10-09 16:31:38.000000000 -0400
\r
3 +++ linux-2.6.23.sqlzma/fs/Kconfig 2007-10-14 13:19:21.000000000 -0400
\r
4 @@ -1364,6 +1364,72 @@
\r
9 + tristate "SquashFS 3.2 - Squashed file system support"
\r
10 + select ZLIB_INFLATE
\r
12 + Saying Y here includes support for SquashFS 3.2 (a Compressed Read-
\r
13 + Only File System). Squashfs is a highly compressed read-only
\r
14 + filesystem for Linux. It uses zlib and/or LZMA compression to compress
\r
15 + both files, inodes and directories. Inodes in the system are very
\r
16 + small and all blocks are packed to minimise data overhead. Block sizes
\r
17 + greater than 4K are supported up to a maximum of 64K. SquashFS 3.2
\r
18 + supports 64 bit filesystems and files (larger than 4GB), full uid/gid
\r
19 + information, hard links and timestamps.
\r
21 + Squashfs is intended for general read-only filesystem use, for archival
\r
22 + use (i.e. in cases where a .tar.gz file may be used), and in embedded
\r
23 + systems where low overhead is needed. Further information and
\r
24 + filesystem tools are available from http://squashfs.sourceforge.net.
\r
26 + If you want to compile this as a module ( = code which can be
\r
27 + inserted in and removed from the running kernel whenever you want),
\r
28 + say M here and read <file:Documentation/modules.txt>. The module
\r
29 + will be called squashfs. Note that the root file system (the one
\r
30 + containing the directory /) cannot be compiled as a module.
\r
34 +config SQUASHFS_EMBEDDED
\r
36 + bool "Additional options for memory-constrained systems"
\r
37 + depends on SQUASHFS
\r
40 + Saying Y here allows you to specify cache sizes and how Squashfs
\r
41 + allocates memory. This is only intended for memory constrained
\r
46 +config SQUASHFS_FRAGMENT_CACHE_SIZE
\r
47 + int "Number of fragments cached" if SQUASHFS_EMBEDDED
\r
48 + depends on SQUASHFS
\r
51 + By default SquashFS caches the last 3 fragments read from
\r
52 + the filesystem. Increasing this amount may mean SquashFS
\r
53 + has to re-read fragments less often from disk, at the expense
\r
54 + of extra system memory. Decreasing this amount will mean
\r
55 + SquashFS uses less memory at the expense of extra reads from disk.
\r
57 + Note there must be at least one cached fragment. Anything
\r
58 + much more than three will probably not make much difference.
\r
60 +config SQUASHFS_VMALLOC
\r
61 + bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED
\r
62 + depends on SQUASHFS
\r
65 + By default SquashFS uses kmalloc to obtain fragment cache memory.
\r
66 + Kmalloc memory is the standard kernel allocator, but it can fail
\r
67 + on memory constrained systems. Because of the way Vmalloc works,
\r
68 + Vmalloc can succeed when kmalloc fails. Specifying this option
\r
69 + will make SquashFS always use Vmalloc to allocate the
\r
70 + fragment cache memory.
\r
75 tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
\r
77 diff -urN linux-2.6.23/fs/Makefile linux-2.6.23.sqlzma/fs/Makefile
\r
78 --- linux-2.6.23/fs/Makefile 2007-10-09 16:31:38.000000000 -0400
\r
79 +++ linux-2.6.23.sqlzma/fs/Makefile 2007-10-14 10:24:31.000000000 -0400
\r
81 obj-$(CONFIG_JBD2) += jbd2/
\r
82 obj-$(CONFIG_EXT2_FS) += ext2/
\r
83 obj-$(CONFIG_CRAMFS) += cramfs/
\r
84 +obj-$(CONFIG_SQUASHFS) += squashfs/
\r
86 obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
\r
87 obj-$(CONFIG_CODA_FS) += coda/
\r
88 diff -urN linux-2.6.23/fs/squashfs/LzmaDecode.c linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.c
\r
89 --- linux-2.6.23/fs/squashfs/LzmaDecode.c 1969-12-31 19:00:00.000000000 -0500
\r
90 +++ linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.c 2007-10-14 12:44:42.000000000 -0400
\r
94 + LZMA Decoder (optimized for Speed version)
\r
96 + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
\r
97 + http://www.7-zip.org/
\r
99 + LZMA SDK is licensed under two licenses:
\r
100 + 1) GNU Lesser General Public License (GNU LGPL)
\r
101 + 2) Common Public License (CPL)
\r
102 + It means that you can select one of these two licenses and
\r
103 + follow rules of that license.
\r
105 + SPECIAL EXCEPTION:
\r
106 + Igor Pavlov, as the author of this Code, expressly permits you to
\r
107 + statically or dynamically link your Code (or bind by name) to the
\r
108 + interfaces of this file without subjecting your linked Code to the
\r
109 + terms of the CPL or GNU LGPL. Any modifications or additions
\r
110 + to this file, however, are subject to the LGPL or CPL terms.
\r
113 +#include "LzmaDecode.h"
\r
115 +#define kNumTopBits 24
\r
116 +#define kTopValue ((UInt32)1 << kNumTopBits)
\r
118 +#define kNumBitModelTotalBits 11
\r
119 +#define kBitModelTotal (1 << kNumBitModelTotalBits)
\r
120 +#define kNumMoveBits 5
\r
122 +#define RC_READ_BYTE (*Buffer++)
\r
124 +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
\r
125 + { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
\r
127 +#ifdef _LZMA_IN_CB
\r
129 +#define RC_TEST { if (Buffer == BufferLim) \
\r
130 + { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
\r
131 + BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
\r
133 +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
\r
137 +#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
\r
139 +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
\r
143 +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
\r
145 +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
\r
146 +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
\r
147 +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
\r
149 +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
\r
150 + { UpdateBit0(p); mi <<= 1; A0; } else \
\r
151 + { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
\r
153 +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
\r
155 +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
\r
156 + { int i = numLevels; res = 1; \
\r
157 + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
\r
158 + res -= (1 << numLevels); }
\r
161 +#define kNumPosBitsMax 4
\r
162 +#define kNumPosStatesMax (1 << kNumPosBitsMax)
\r
164 +#define kLenNumLowBits 3
\r
165 +#define kLenNumLowSymbols (1 << kLenNumLowBits)
\r
166 +#define kLenNumMidBits 3
\r
167 +#define kLenNumMidSymbols (1 << kLenNumMidBits)
\r
168 +#define kLenNumHighBits 8
\r
169 +#define kLenNumHighSymbols (1 << kLenNumHighBits)
\r
171 +#define LenChoice 0
\r
172 +#define LenChoice2 (LenChoice + 1)
\r
173 +#define LenLow (LenChoice2 + 1)
\r
174 +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
\r
175 +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
\r
176 +#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
\r
179 +#define kNumStates 12
\r
180 +#define kNumLitStates 7
\r
182 +#define kStartPosModelIndex 4
\r
183 +#define kEndPosModelIndex 14
\r
184 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
\r
186 +#define kNumPosSlotBits 6
\r
187 +#define kNumLenToPosStates 4
\r
189 +#define kNumAlignBits 4
\r
190 +#define kAlignTableSize (1 << kNumAlignBits)
\r
192 +#define kMatchMinLen 2
\r
195 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
\r
196 +#define IsRepG0 (IsRep + kNumStates)
\r
197 +#define IsRepG1 (IsRepG0 + kNumStates)
\r
198 +#define IsRepG2 (IsRepG1 + kNumStates)
\r
199 +#define IsRep0Long (IsRepG2 + kNumStates)
\r
200 +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
\r
201 +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
\r
202 +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
\r
203 +#define LenCoder (Align + kAlignTableSize)
\r
204 +#define RepLenCoder (LenCoder + kNumLenProbs)
\r
205 +#define Literal (RepLenCoder + kNumLenProbs)
\r
207 +#if Literal != LZMA_BASE_SIZE
\r
208 +StopCompilingDueBUG
\r
211 +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
\r
213 + unsigned char prop0;
\r
214 + if (size < LZMA_PROPERTIES_SIZE)
\r
215 + return LZMA_RESULT_DATA_ERROR;
\r
216 + prop0 = propsData[0];
\r
217 + if (prop0 >= (9 * 5 * 5))
\r
218 + return LZMA_RESULT_DATA_ERROR;
\r
220 + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
\r
221 + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
\r
222 + propsRes->lc = prop0;
\r
224 + unsigned char remainder = (unsigned char)(prop0 / 9);
\r
225 + propsRes->lc = prop0 % 9;
\r
226 + propsRes->pb = remainder / 5;
\r
227 + propsRes->lp = remainder % 5;
\r
231 + #ifdef _LZMA_OUT_READ
\r
234 + propsRes->DictionarySize = 0;
\r
235 + for (i = 0; i < 4; i++)
\r
236 + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
\r
237 + if (propsRes->DictionarySize == 0)
\r
238 + propsRes->DictionarySize = 1;
\r
241 + return LZMA_RESULT_OK;
\r
244 +#define kLzmaStreamWasFinishedId (-1)
\r
246 +int LzmaDecode(CLzmaDecoderState *vs,
\r
247 + #ifdef _LZMA_IN_CB
\r
248 + ILzmaInCallback *InCallback,
\r
250 + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
\r
252 + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
\r
254 + CProb *p = vs->Probs;
\r
255 + SizeT nowPos = 0;
\r
256 + Byte previousByte = 0;
\r
257 + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
\r
258 + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
\r
259 + int lc = vs->Properties.lc;
\r
261 + #ifdef _LZMA_OUT_READ
\r
263 + UInt32 Range = vs->Range;
\r
264 + UInt32 Code = vs->Code;
\r
265 + #ifdef _LZMA_IN_CB
\r
266 + const Byte *Buffer = vs->Buffer;
\r
267 + const Byte *BufferLim = vs->BufferLim;
\r
269 + const Byte *Buffer = inStream;
\r
270 + const Byte *BufferLim = inStream + inSize;
\r
272 + int state = vs->State;
\r
273 + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
\r
274 + int len = vs->RemainLen;
\r
275 + UInt32 globalPos = vs->GlobalPos;
\r
276 + UInt32 distanceLimit = vs->DistanceLimit;
\r
278 + Byte *dictionary = vs->Dictionary;
\r
279 + UInt32 dictionarySize = vs->Properties.DictionarySize;
\r
280 + UInt32 dictionaryPos = vs->DictionaryPos;
\r
282 + Byte tempDictionary[4];
\r
284 + #ifndef _LZMA_IN_CB
\r
285 + *inSizeProcessed = 0;
\r
287 + *outSizeProcessed = 0;
\r
288 + if (len == kLzmaStreamWasFinishedId)
\r
289 + return LZMA_RESULT_OK;
\r
291 + if (dictionarySize == 0)
\r
293 + dictionary = tempDictionary;
\r
294 + dictionarySize = 1;
\r
295 + tempDictionary[0] = vs->TempDictionary[0];
\r
298 + if (len == kLzmaNeedInitId)
\r
301 + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
\r
303 + for (i = 0; i < numProbs; i++)
\r
304 + p[i] = kBitModelTotal >> 1;
\r
305 + rep0 = rep1 = rep2 = rep3 = 1;
\r
308 + distanceLimit = 0;
\r
309 + dictionaryPos = 0;
\r
310 + dictionary[dictionarySize - 1] = 0;
\r
311 + #ifdef _LZMA_IN_CB
\r
314 + RC_INIT(inStream, inSize);
\r
319 + while(len != 0 && nowPos < outSize)
\r
321 + UInt32 pos = dictionaryPos - rep0;
\r
322 + if (pos >= dictionarySize)
\r
323 + pos += dictionarySize;
\r
324 + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
\r
325 + if (++dictionaryPos == dictionarySize)
\r
326 + dictionaryPos = 0;
\r
329 + if (dictionaryPos == 0)
\r
330 + previousByte = dictionary[dictionarySize - 1];
\r
332 + previousByte = dictionary[dictionaryPos - 1];
\r
334 + #else /* if !_LZMA_OUT_READ */
\r
337 + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
\r
339 + const Byte *Buffer;
\r
340 + const Byte *BufferLim;
\r
344 + #ifndef _LZMA_IN_CB
\r
345 + *inSizeProcessed = 0;
\r
347 + *outSizeProcessed = 0;
\r
351 + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
\r
352 + for (i = 0; i < numProbs; i++)
\r
353 + p[i] = kBitModelTotal >> 1;
\r
356 + #ifdef _LZMA_IN_CB
\r
359 + RC_INIT(inStream, inSize);
\r
362 + #endif /* _LZMA_OUT_READ */
\r
364 + while(nowPos < outSize)
\r
368 + int posState = (int)(
\r
370 + #ifdef _LZMA_OUT_READ
\r
376 + prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
\r
381 + prob = p + Literal + (LZMA_LIT_SIZE *
\r
384 + #ifdef _LZMA_OUT_READ
\r
388 + & literalPosMask) << lc) + (previousByte >> (8 - lc))));
\r
390 + if (state >= kNumLitStates)
\r
393 + #ifdef _LZMA_OUT_READ
\r
394 + UInt32 pos = dictionaryPos - rep0;
\r
395 + if (pos >= dictionarySize)
\r
396 + pos += dictionarySize;
\r
397 + matchByte = dictionary[pos];
\r
399 + matchByte = outStream[nowPos - rep0];
\r
406 + bit = (matchByte & 0x100);
\r
407 + probLit = prob + 0x100 + bit + symbol;
\r
408 + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
\r
410 + while (symbol < 0x100);
\r
412 + while (symbol < 0x100)
\r
414 + CProb *probLit = prob + symbol;
\r
415 + RC_GET_BIT(probLit, symbol)
\r
417 + previousByte = (Byte)symbol;
\r
419 + outStream[nowPos++] = previousByte;
\r
420 + #ifdef _LZMA_OUT_READ
\r
421 + if (distanceLimit < dictionarySize)
\r
424 + dictionary[dictionaryPos] = previousByte;
\r
425 + if (++dictionaryPos == dictionarySize)
\r
426 + dictionaryPos = 0;
\r
428 + if (state < 4) state = 0;
\r
429 + else if (state < 10) state -= 3;
\r
434 + UpdateBit1(prob);
\r
435 + prob = p + IsRep + state;
\r
438 + UpdateBit0(prob);
\r
442 + state = state < kNumLitStates ? 0 : 3;
\r
443 + prob = p + LenCoder;
\r
447 + UpdateBit1(prob);
\r
448 + prob = p + IsRepG0 + state;
\r
451 + UpdateBit0(prob);
\r
452 + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
\r
455 + #ifdef _LZMA_OUT_READ
\r
458 + UpdateBit0(prob);
\r
460 + #ifdef _LZMA_OUT_READ
\r
461 + if (distanceLimit == 0)
\r
465 + return LZMA_RESULT_DATA_ERROR;
\r
467 + state = state < kNumLitStates ? 9 : 11;
\r
468 + #ifdef _LZMA_OUT_READ
\r
469 + pos = dictionaryPos - rep0;
\r
470 + if (pos >= dictionarySize)
\r
471 + pos += dictionarySize;
\r
472 + previousByte = dictionary[pos];
\r
473 + dictionary[dictionaryPos] = previousByte;
\r
474 + if (++dictionaryPos == dictionarySize)
\r
475 + dictionaryPos = 0;
\r
477 + previousByte = outStream[nowPos - rep0];
\r
479 + outStream[nowPos++] = previousByte;
\r
480 + #ifdef _LZMA_OUT_READ
\r
481 + if (distanceLimit < dictionarySize)
\r
489 + UpdateBit1(prob);
\r
495 + UpdateBit1(prob);
\r
496 + prob = p + IsRepG1 + state;
\r
499 + UpdateBit0(prob);
\r
504 + UpdateBit1(prob);
\r
505 + prob = p + IsRepG2 + state;
\r
508 + UpdateBit0(prob);
\r
513 + UpdateBit1(prob);
\r
522 + state = state < kNumLitStates ? 8 : 11;
\r
523 + prob = p + RepLenCoder;
\r
526 + int numBits, offset;
\r
527 + CProb *probLen = prob + LenChoice;
\r
530 + UpdateBit0(probLen);
\r
531 + probLen = prob + LenLow + (posState << kLenNumLowBits);
\r
533 + numBits = kLenNumLowBits;
\r
537 + UpdateBit1(probLen);
\r
538 + probLen = prob + LenChoice2;
\r
541 + UpdateBit0(probLen);
\r
542 + probLen = prob + LenMid + (posState << kLenNumMidBits);
\r
543 + offset = kLenNumLowSymbols;
\r
544 + numBits = kLenNumMidBits;
\r
548 + UpdateBit1(probLen);
\r
549 + probLen = prob + LenHigh;
\r
550 + offset = kLenNumLowSymbols + kLenNumMidSymbols;
\r
551 + numBits = kLenNumHighBits;
\r
554 + RangeDecoderBitTreeDecode(probLen, numBits, len);
\r
561 + state += kNumLitStates;
\r
562 + prob = p + PosSlot +
\r
563 + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
\r
564 + kNumPosSlotBits);
\r
565 + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
\r
566 + if (posSlot >= kStartPosModelIndex)
\r
568 + int numDirectBits = ((posSlot >> 1) - 1);
\r
569 + rep0 = (2 | ((UInt32)posSlot & 1));
\r
570 + if (posSlot < kEndPosModelIndex)
\r
572 + rep0 <<= numDirectBits;
\r
573 + prob = p + SpecPos + rep0 - posSlot - 1;
\r
577 + numDirectBits -= kNumAlignBits;
\r
583 + if (Code >= Range)
\r
589 + while (--numDirectBits != 0);
\r
590 + prob = p + Align;
\r
591 + rep0 <<= kNumAlignBits;
\r
592 + numDirectBits = kNumAlignBits;
\r
599 + CProb *prob3 = prob + mi;
\r
600 + RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
\r
603 + while(--numDirectBits != 0);
\r
608 + if (++rep0 == (UInt32)(0))
\r
610 + /* it's for stream version */
\r
611 + len = kLzmaStreamWasFinishedId;
\r
616 + len += kMatchMinLen;
\r
617 + #ifdef _LZMA_OUT_READ
\r
618 + if (rep0 > distanceLimit)
\r
620 + if (rep0 > nowPos)
\r
622 + return LZMA_RESULT_DATA_ERROR;
\r
624 + #ifdef _LZMA_OUT_READ
\r
625 + if (dictionarySize - distanceLimit > (UInt32)len)
\r
626 + distanceLimit += len;
\r
628 + distanceLimit = dictionarySize;
\r
633 + #ifdef _LZMA_OUT_READ
\r
634 + UInt32 pos = dictionaryPos - rep0;
\r
635 + if (pos >= dictionarySize)
\r
636 + pos += dictionarySize;
\r
637 + previousByte = dictionary[pos];
\r
638 + dictionary[dictionaryPos] = previousByte;
\r
639 + if (++dictionaryPos == dictionarySize)
\r
640 + dictionaryPos = 0;
\r
642 + previousByte = outStream[nowPos - rep0];
\r
645 + outStream[nowPos++] = previousByte;
\r
647 + while(len != 0 && nowPos < outSize);
\r
652 + #ifdef _LZMA_OUT_READ
\r
653 + vs->Range = Range;
\r
655 + vs->DictionaryPos = dictionaryPos;
\r
656 + vs->GlobalPos = globalPos + (UInt32)nowPos;
\r
657 + vs->DistanceLimit = distanceLimit;
\r
658 + vs->Reps[0] = rep0;
\r
659 + vs->Reps[1] = rep1;
\r
660 + vs->Reps[2] = rep2;
\r
661 + vs->Reps[3] = rep3;
\r
662 + vs->State = state;
\r
663 + vs->RemainLen = len;
\r
664 + vs->TempDictionary[0] = tempDictionary[0];
\r
667 + #ifdef _LZMA_IN_CB
\r
668 + vs->Buffer = Buffer;
\r
669 + vs->BufferLim = BufferLim;
\r
671 + *inSizeProcessed = (SizeT)(Buffer - inStream);
\r
673 + *outSizeProcessed = nowPos;
\r
674 + return LZMA_RESULT_OK;
\r
676 diff -urN linux-2.6.23/fs/squashfs/LzmaDecode.h linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.h
\r
677 --- linux-2.6.23/fs/squashfs/LzmaDecode.h 1969-12-31 19:00:00.000000000 -0500
\r
678 +++ linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.h 2007-10-14 12:44:42.000000000 -0400
\r
682 + LZMA Decoder interface
\r
684 + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
\r
685 + http://www.7-zip.org/
\r
687 + LZMA SDK is licensed under two licenses:
\r
688 + 1) GNU Lesser General Public License (GNU LGPL)
\r
689 + 2) Common Public License (CPL)
\r
690 + It means that you can select one of these two licenses and
\r
691 + follow rules of that license.
\r
693 + SPECIAL EXCEPTION:
\r
694 + Igor Pavlov, as the author of this code, expressly permits you to
\r
695 + statically or dynamically link your code (or bind by name) to the
\r
696 + interfaces of this file without subjecting your linked code to the
\r
697 + terms of the CPL or GNU LGPL. Any modifications or additions
\r
698 + to this file, however, are subject to the LGPL or CPL terms.
\r
701 +#ifndef __LZMADECODE_H
\r
702 +#define __LZMADECODE_H
\r
704 +#include "LzmaTypes.h"
\r
706 +/* #define _LZMA_IN_CB */
\r
707 +/* Use callback for input data */
\r
709 +/* #define _LZMA_OUT_READ */
\r
710 +/* Use read function for output data */
\r
712 +/* #define _LZMA_PROB32 */
\r
713 +/* It can increase speed on some 32-bit CPUs,
\r
714 + but memory usage will be doubled in that case */
\r
716 +/* #define _LZMA_LOC_OPT */
\r
717 +/* Enable local speed optimizations inside code */
\r
719 +#ifdef _LZMA_PROB32
\r
720 +#define CProb UInt32
\r
722 +#define CProb UInt16
\r
725 +#define LZMA_RESULT_OK 0
\r
726 +#define LZMA_RESULT_DATA_ERROR 1
\r
728 +#ifdef _LZMA_IN_CB
\r
729 +typedef struct _ILzmaInCallback
\r
731 + int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
\r
732 +} ILzmaInCallback;
\r
735 +#define LZMA_BASE_SIZE 1846
\r
736 +#define LZMA_LIT_SIZE 768
\r
738 +#define LZMA_PROPERTIES_SIZE 5
\r
740 +typedef struct _CLzmaProperties
\r
745 + #ifdef _LZMA_OUT_READ
\r
746 + UInt32 DictionarySize;
\r
750 +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
\r
752 +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
\r
754 +#define kLzmaNeedInitId (-2)
\r
756 +typedef struct _CLzmaDecoderState
\r
758 + CLzmaProperties Properties;
\r
761 + #ifdef _LZMA_IN_CB
\r
762 + const unsigned char *Buffer;
\r
763 + const unsigned char *BufferLim;
\r
766 + #ifdef _LZMA_OUT_READ
\r
767 + unsigned char *Dictionary;
\r
770 + UInt32 DictionaryPos;
\r
771 + UInt32 GlobalPos;
\r
772 + UInt32 DistanceLimit;
\r
776 + unsigned char TempDictionary[4];
\r
778 +} CLzmaDecoderState;
\r
780 +#ifdef _LZMA_OUT_READ
\r
781 +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
\r
784 +int LzmaDecode(CLzmaDecoderState *vs,
\r
785 + #ifdef _LZMA_IN_CB
\r
786 + ILzmaInCallback *inCallback,
\r
788 + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
\r
790 + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
\r
793 diff -urN linux-2.6.23/fs/squashfs/LzmaTypes.h linux-2.6.23.sqlzma/fs/squashfs/LzmaTypes.h
\r
794 --- linux-2.6.23/fs/squashfs/LzmaTypes.h 1969-12-31 19:00:00.000000000 -0500
\r
795 +++ linux-2.6.23.sqlzma/fs/squashfs/LzmaTypes.h 2007-10-14 13:00:30.000000000 -0400
\r
800 +Types for LZMA Decoder
\r
802 +This file written and distributed to public domain by Igor Pavlov.
\r
803 +This file is part of LZMA SDK 4.40 (2006-05-01)
\r
806 +#ifndef __LZMATYPES_H
\r
807 +#define __LZMATYPES_H
\r
809 +#ifndef _7ZIP_BYTE_DEFINED
\r
810 +#define _7ZIP_BYTE_DEFINED
\r
811 +typedef unsigned char Byte;
\r
814 +#ifndef _7ZIP_UINT16_DEFINED
\r
815 +#define _7ZIP_UINT16_DEFINED
\r
816 +typedef unsigned short UInt16;
\r
819 +#ifndef _7ZIP_UINT32_DEFINED
\r
820 +#define _7ZIP_UINT32_DEFINED
\r
821 +#ifdef _LZMA_UINT32_IS_ULONG
\r
822 +typedef unsigned long UInt32;
\r
824 +typedef unsigned int UInt32;
\r
828 +/* #define _LZMA_SYSTEM_SIZE_T */
\r
829 +/* Use system's size_t. You can use it to enable 64-bit sizes supporting */
\r
831 +#ifndef _7ZIP_SIZET_DEFINED
\r
832 +#define _7ZIP_SIZET_DEFINED
\r
833 +#ifdef _LZMA_SYSTEM_SIZE_T
\r
834 +#include <stddef.h>
\r
835 +typedef size_t SizeT;
\r
837 +typedef UInt32 SizeT;
\r
842 diff -urN linux-2.6.23/fs/squashfs/Makefile linux-2.6.23.sqlzma/fs/squashfs/Makefile
\r
843 --- linux-2.6.23/fs/squashfs/Makefile 1969-12-31 19:00:00.000000000 -0500
\r
844 +++ linux-2.6.23.sqlzma/fs/squashfs/Makefile 2007-10-14 12:56:24.000000000 -0400
\r
847 +# Copyright (C) 2006 Junjiro Okajima
\r
848 +# Copyright (C) 2006 Tomas Matejicek, slax.org
\r
850 +# LICENSE follows the described one in lzma.txt.
\r
852 +# $Id: Makefile,v 1.3 2006/11/27 03:54:58 jro Exp $
\r
855 +# Makefile for the linux squashfs routines.
\r
858 +obj-$(CONFIG_SQUASHFS) += unlzma.o sqlzma.o squashfs.o
\r
859 +unlzma-y += module.o
\r
860 +sqlzma-y += uncomp.o
\r
861 +squashfs-y += inode.o
\r
862 +squashfs-y += squashfs2_0.o
\r
864 diff -urN linux-2.6.23/fs/squashfs/inode.c linux-2.6.23.sqlzma/fs/squashfs/inode.c
\r
865 --- linux-2.6.23/fs/squashfs/inode.c 1969-12-31 19:00:00.000000000 -0500
\r
866 +++ linux-2.6.23.sqlzma/fs/squashfs/inode.c 2007-10-14 10:29:23.000000000 -0400
\r
869 + * Squashfs - a compressed read only filesystem for Linux
\r
871 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
\r
872 + * Phillip Lougher <phillip@lougher.org.uk>
\r
874 + * This program is free software; you can redistribute it and/or
\r
875 + * modify it under the terms of the GNU General Public License
\r
876 + * as published by the Free Software Foundation; either version 2,
\r
877 + * or (at your option) any later version.
\r
879 + * This program is distributed in the hope that it will be useful,
\r
880 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
881 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
882 + * GNU General Public License for more details.
\r
884 + * You should have received a copy of the GNU General Public License
\r
885 + * along with this program; if not, write to the Free Software
\r
886 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
891 +#include <linux/squashfs_fs.h>
\r
892 +#include <linux/module.h>
\r
893 +#include <linux/zlib.h>
\r
894 +#include <linux/fs.h>
\r
895 +#include <linux/squashfs_fs_sb.h>
\r
896 +#include <linux/squashfs_fs_i.h>
\r
897 +#include <linux/buffer_head.h>
\r
898 +#include <linux/vfs.h>
\r
899 +#include <linux/vmalloc.h>
\r
900 +#include <linux/smp_lock.h>
\r
901 +#include <linux/sched.h>
\r
902 +#include <linux/exportfs.h>
\r
904 +#include "squashfs.h"
\r
905 +#include "sqlzma.h"
\r
906 +#include "sqmagic.h"
\r
908 +#undef KeepPreemptive
\r
909 +#if defined(CONFIG_PREEMPT) && !defined(UnsquashNoPreempt)
\r
910 +#define KeepPreemptive
\r
914 +#ifdef KeepPreemptive
\r
915 + struct mutex mtx;
\r
917 + unsigned char read_data[SQUASHFS_FILE_MAX_SIZE];
\r
918 + struct sqlzma_un un;
\r
920 +static DEFINE_PER_CPU(struct sqlzma *, sqlzma);
\r
922 +#define dpri(fmt, args...) /* printk("%s:%d: " fmt, __func__, __LINE__, ##args) */
\r
923 +#define dpri_un(un) dpri("un{%d, {%d %p}, {%d %p}, {%d %p}}\n", \
\r
924 + (un)->un_lzma, (un)->un_a[0].sz, (un)->un_a[0].buf, \
\r
925 + (un)->un_a[1].sz, (un)->un_a[1].buf, \
\r
926 + (un)->un_a[2].sz, (un)->un_a[2].buf)
\r
928 +static void vfs_read_inode(struct inode *i);
\r
929 +static struct dentry *squashfs_get_parent(struct dentry *child);
\r
930 +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode);
\r
931 +static int squashfs_statfs(struct dentry *, struct kstatfs *);
\r
932 +static int squashfs_symlink_readpage(struct file *file, struct page *page);
\r
933 +static long long read_blocklist(struct inode *inode, int index,
\r
934 + int readahead_blks, char *block_list,
\r
935 + unsigned short **block_p, unsigned int *bsize);
\r
936 +static int squashfs_readpage(struct file *file, struct page *page);
\r
937 +static int squashfs_readpage4K(struct file *file, struct page *page);
\r
938 +static int squashfs_readdir(struct file *, void *, filldir_t);
\r
939 +static struct dentry *squashfs_lookup(struct inode *, struct dentry *,
\r
940 + struct nameidata *);
\r
941 +static int squashfs_remount(struct super_block *s, int *flags, char *data);
\r
942 +static void squashfs_put_super(struct super_block *);
\r
943 +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *,
\r
944 + struct vfsmount *);
\r
945 +static struct inode *squashfs_alloc_inode(struct super_block *sb);
\r
946 +static void squashfs_destroy_inode(struct inode *inode);
\r
947 +static int init_inodecache(void);
\r
948 +static void destroy_inodecache(void);
\r
950 +static struct file_system_type squashfs_fs_type = {
\r
951 + .owner = THIS_MODULE,
\r
952 + .name = "squashfs",
\r
953 + .get_sb = squashfs_get_sb,
\r
954 + .kill_sb = kill_block_super,
\r
955 + .fs_flags = FS_REQUIRES_DEV
\r
958 +static const unsigned char squashfs_filetype_table[] = {
\r
959 + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
\r
962 +static struct super_operations squashfs_super_ops = {
\r
963 + .alloc_inode = squashfs_alloc_inode,
\r
964 + .destroy_inode = squashfs_destroy_inode,
\r
965 + .statfs = squashfs_statfs,
\r
966 + .put_super = squashfs_put_super,
\r
967 + .remount_fs = squashfs_remount
\r
970 +static struct super_operations squashfs_export_super_ops = {
\r
971 + .alloc_inode = squashfs_alloc_inode,
\r
972 + .destroy_inode = squashfs_destroy_inode,
\r
973 + .statfs = squashfs_statfs,
\r
974 + .put_super = squashfs_put_super,
\r
975 + .read_inode = vfs_read_inode
\r
978 +static struct export_operations squashfs_export_ops = {
\r
979 + .get_parent = squashfs_get_parent
\r
982 +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = {
\r
983 + .readpage = squashfs_symlink_readpage
\r
986 +SQSH_EXTERN const struct address_space_operations squashfs_aops = {
\r
987 + .readpage = squashfs_readpage
\r
990 +SQSH_EXTERN const struct address_space_operations squashfs_aops_4K = {
\r
991 + .readpage = squashfs_readpage4K
\r
994 +static const struct file_operations squashfs_dir_ops = {
\r
995 + .read = generic_read_dir,
\r
996 + .readdir = squashfs_readdir
\r
999 +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {
\r
1000 + .lookup = squashfs_lookup
\r
1004 +static struct buffer_head *get_block_length(struct super_block *s,
\r
1005 + int *cur_index, int *offset, int *c_byte)
\r
1007 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
1008 + unsigned short temp;
\r
1009 + struct buffer_head *bh;
\r
1011 + if (!(bh = sb_bread(s, *cur_index)))
\r
1014 + if (msblk->devblksize - *offset == 1) {
\r
1015 + if (msblk->swap)
\r
1016 + ((unsigned char *) &temp)[1] = *((unsigned char *)
\r
1017 + (bh->b_data + *offset));
\r
1019 + ((unsigned char *) &temp)[0] = *((unsigned char *)
\r
1020 + (bh->b_data + *offset));
\r
1022 + if (!(bh = sb_bread(s, ++(*cur_index))))
\r
1024 + if (msblk->swap)
\r
1025 + ((unsigned char *) &temp)[0] = *((unsigned char *)
\r
1028 + ((unsigned char *) &temp)[1] = *((unsigned char *)
\r
1033 + if (msblk->swap) {
\r
1034 + ((unsigned char *) &temp)[1] = *((unsigned char *)
\r
1035 + (bh->b_data + *offset));
\r
1036 + ((unsigned char *) &temp)[0] = *((unsigned char *)
\r
1037 + (bh->b_data + *offset + 1));
\r
1039 + ((unsigned char *) &temp)[0] = *((unsigned char *)
\r
1040 + (bh->b_data + *offset));
\r
1041 + ((unsigned char *) &temp)[1] = *((unsigned char *)
\r
1042 + (bh->b_data + *offset + 1));
\r
1048 + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
\r
1049 + if (*offset == msblk->devblksize) {
\r
1051 + if (!(bh = sb_bread(s, ++(*cur_index))))
\r
1055 + if (*((unsigned char *) (bh->b_data + *offset)) !=
\r
1056 + SQUASHFS_MARKER_BYTE) {
\r
1057 + ERROR("Metadata block marker corrupt @ %x\n",
\r
1071 +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
\r
1072 + long long index, unsigned int length,
\r
1073 + long long *next_index, int srclength)
\r
1075 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
1076 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
1077 + struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
\r
1078 + msblk->devblksize_log2) + 2];
\r
1079 + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
\r
1080 + unsigned int cur_index = index >> msblk->devblksize_log2;
\r
1081 + int bytes, avail_bytes, b = 0, k = 0;
\r
1082 + unsigned int compressed;
\r
1083 + unsigned int c_byte = length;
\r
1086 + bytes = msblk->devblksize - offset;
\r
1087 + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
\r
1088 + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
\r
1090 + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed
\r
1091 + ? "" : "un", (unsigned int) c_byte, srclength);
\r
1093 + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used)
\r
1094 + goto read_failure;
\r
1096 + if (!(bh[0] = sb_getblk(s, cur_index)))
\r
1097 + goto block_release;
\r
1099 + for (b = 1; bytes < c_byte; b++) {
\r
1100 + if (!(bh[b] = sb_getblk(s, ++cur_index)))
\r
1101 + goto block_release;
\r
1102 + bytes += msblk->devblksize;
\r
1104 + ll_rw_block(READ, b, bh);
\r
1106 + if (index < 0 || (index + 2) > sblk->bytes_used)
\r
1107 + goto read_failure;
\r
1109 + if (!(bh[0] = get_block_length(s, &cur_index, &offset,
\r
1111 + goto read_failure;
\r
1113 + bytes = msblk->devblksize - offset;
\r
1114 + compressed = SQUASHFS_COMPRESSED(c_byte);
\r
1115 + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
\r
1117 + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
\r
1118 + ? "" : "un", (unsigned int) c_byte);
\r
1120 + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used)
\r
1121 + goto read_failure;
\r
1123 + for (b = 1; bytes < c_byte; b++) {
\r
1124 + if (!(bh[b] = sb_getblk(s, ++cur_index)))
\r
1125 + goto block_release;
\r
1126 + bytes += msblk->devblksize;
\r
1128 + ll_rw_block(READ, b - 1, bh + 1);
\r
1131 + if (compressed) {
\r
1132 + int zlib_err = Z_STREAM_END;
\r
1133 + int rest, start;
\r
1134 + enum {Src, Dst};
\r
1135 + struct sized_buf sbuf[2];
\r
1136 + struct sqlzma *percpu;
\r
1139 + * uncompress block
\r
1141 + for (k = 0; k < b; k++) {
\r
1142 + wait_on_buffer(bh[k]);
\r
1143 + if (!buffer_uptodate(bh[k]))
\r
1144 + goto block_release;
\r
1147 + avail_bytes = 0;
\r
1148 + for (k = 0; !avail_bytes && k < b; k++) {
\r
1149 + avail_bytes = msblk->devblksize - offset;
\r
1150 + if (c_byte < avail_bytes)
\r
1151 + avail_bytes = c_byte;
\r
1152 + if (avail_bytes)
\r
1158 + if (!avail_bytes)
\r
1159 + goto block_release; // nothing to be process
\r
1162 + /* it disables preemption */
\r
1163 + percpu = get_cpu_var(sqlzma);
\r
1164 +#ifdef KeepPreemptive
\r
1165 + put_cpu_var(sqlzma);
\r
1166 + mutex_lock(&percpu->mtx);
\r
1169 + for (; k < b; k++) {
\r
1170 + memcpy(percpu->read_data + bytes, bh[k]->b_data + offset,
\r
1172 + bytes += avail_bytes;
\r
1175 + avail_bytes = msblk->devblksize - offset;
\r
1176 + rest = c_byte - bytes;
\r
1177 + if (rest < avail_bytes)
\r
1178 + avail_bytes = rest;
\r
1181 + sbuf[Src].buf = percpu->read_data;
\r
1182 + sbuf[Src].sz = bytes;
\r
1183 + sbuf[Dst].buf = buffer;
\r
1184 + sbuf[Dst].sz = srclength;
\r
1185 + dpri_un(&percpu->un);
\r
1186 + dpri("src %d %p, dst %d %p\n", sbuf[Src].sz, sbuf[Src].buf,
\r
1187 + sbuf[Dst].sz, sbuf[Dst].buf);
\r
1188 + zlib_err = sqlzma_un(&percpu->un, sbuf + Src, sbuf + Dst);
\r
1189 + bytes = percpu->un.un_reslen;
\r
1191 +#ifdef KeepPreemptive
\r
1192 + mutex_unlock(&percpu->mtx);
\r
1194 + put_cpu_var(sqlzma);
\r
1196 + if (unlikely(zlib_err)) {
\r
1197 + dpri("zlib_err %d\n", zlib_err);
\r
1198 + goto release_mutex;
\r
1203 + for(i = 0; i < b; i++) {
\r
1204 + wait_on_buffer(bh[i]);
\r
1205 + if(!buffer_uptodate(bh[i]))
\r
1206 + goto block_release;
\r
1209 + for (bytes = 0; k < b; k++) {
\r
1210 + avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
\r
1211 + msblk->devblksize - offset :
\r
1213 + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes);
\r
1214 + bytes += avail_bytes;
\r
1221 + *next_index = index + c_byte + (length ? 0 :
\r
1222 + (SQUASHFS_CHECK_DATA(msblk->sblk.flags)
\r
1227 + //mutex_unlock(&msblk->read_data_mutex);
\r
1230 + for (; k < b; k++)
\r
1234 + ERROR("sb_bread failed reading block 0x%x\n", cur_index);
\r
1239 +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
\r
1240 + long long block, unsigned int offset,
\r
1241 + int length, long long *next_block,
\r
1242 + unsigned int *next_offset)
\r
1244 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
1245 + int n, i, bytes, return_length = length;
\r
1246 + long long next_index;
\r
1248 + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
\r
1251 + for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
\r
1252 + if (msblk->block_cache[i].block == block)
\r
1255 + mutex_lock(&msblk->block_cache_mutex);
\r
1257 + if (i == SQUASHFS_CACHED_BLKS) {
\r
1258 + /* read inode header block */
\r
1259 + for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
\r
1260 + n ; n --, i = (i + 1) %
\r
1261 + SQUASHFS_CACHED_BLKS)
\r
1262 + if (msblk->block_cache[i].block !=
\r
1263 + SQUASHFS_USED_BLK)
\r
1267 + wait_queue_t wait;
\r
1269 + init_waitqueue_entry(&wait, current);
\r
1270 + add_wait_queue(&msblk->waitq, &wait);
\r
1271 + set_current_state(TASK_UNINTERRUPTIBLE);
\r
1272 + mutex_unlock(&msblk->block_cache_mutex);
\r
1274 + set_current_state(TASK_RUNNING);
\r
1275 + remove_wait_queue(&msblk->waitq, &wait);
\r
1278 + msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
\r
1280 + if (msblk->block_cache[i].block ==
\r
1281 + SQUASHFS_INVALID_BLK) {
\r
1282 + if (!(msblk->block_cache[i].data =
\r
1283 + kmalloc(SQUASHFS_METADATA_SIZE,
\r
1285 + ERROR("Failed to allocate cache"
\r
1287 + mutex_unlock(&msblk->block_cache_mutex);
\r
1292 + msblk->block_cache[i].block = SQUASHFS_USED_BLK;
\r
1293 + mutex_unlock(&msblk->block_cache_mutex);
\r
1295 + msblk->block_cache[i].length = squashfs_read_data(s,
\r
1296 + msblk->block_cache[i].data, block, 0, &next_index, SQUASHFS_METADATA_SIZE);
\r
1297 + if (msblk->block_cache[i].length == 0) {
\r
1298 + ERROR("Unable to read cache block [%llx:%x]\n",
\r
1300 + mutex_lock(&msblk->block_cache_mutex);
\r
1301 + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
\r
1302 + kfree(msblk->block_cache[i].data);
\r
1303 + wake_up(&msblk->waitq);
\r
1304 + mutex_unlock(&msblk->block_cache_mutex);
\r
1308 + mutex_lock(&msblk->block_cache_mutex);
\r
1309 + wake_up(&msblk->waitq);
\r
1310 + msblk->block_cache[i].block = block;
\r
1311 + msblk->block_cache[i].next_index = next_index;
\r
1312 + TRACE("Read cache block [%llx:%x]\n", block, offset);
\r
1315 + if (msblk->block_cache[i].block != block) {
\r
1316 + mutex_unlock(&msblk->block_cache_mutex);
\r
1320 + bytes = msblk->block_cache[i].length - offset;
\r
1322 + if (bytes < 1) {
\r
1323 + mutex_unlock(&msblk->block_cache_mutex);
\r
1325 + } else if (bytes >= length) {
\r
1327 + memcpy(buffer, msblk->block_cache[i].data +
\r
1328 + offset, length);
\r
1329 + if (msblk->block_cache[i].length - offset == length) {
\r
1330 + *next_block = msblk->block_cache[i].next_index;
\r
1331 + *next_offset = 0;
\r
1333 + *next_block = block;
\r
1334 + *next_offset = offset + length;
\r
1336 + mutex_unlock(&msblk->block_cache_mutex);
\r
1340 + memcpy(buffer, msblk->block_cache[i].data +
\r
1342 + buffer += bytes;
\r
1344 + block = msblk->block_cache[i].next_index;
\r
1345 + mutex_unlock(&msblk->block_cache_mutex);
\r
1346 + length -= bytes;
\r
1352 + return return_length;
\r
1358 +static int get_fragment_location(struct super_block *s, unsigned int fragment,
\r
1359 + long long *fragment_start_block,
\r
1360 + unsigned int *fragment_size)
\r
1362 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
1363 + long long start_block =
\r
1364 + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
\r
1365 + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
\r
1366 + struct squashfs_fragment_entry fragment_entry;
\r
1368 + if (msblk->swap) {
\r
1369 + struct squashfs_fragment_entry sfragment_entry;
\r
1371 + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
\r
1372 + start_block, offset,
\r
1373 + sizeof(sfragment_entry), &start_block,
\r
1376 + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
\r
1378 + if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
\r
1379 + start_block, offset,
\r
1380 + sizeof(fragment_entry), &start_block,
\r
1384 + *fragment_start_block = fragment_entry.start_block;
\r
1385 + *fragment_size = fragment_entry.size;
\r
1394 +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
\r
1395 + squashfs_fragment_cache *fragment)
\r
1397 + mutex_lock(&msblk->fragment_mutex);
\r
1398 + fragment->locked --;
\r
1399 + wake_up(&msblk->fragment_wait_queue);
\r
1400 + mutex_unlock(&msblk->fragment_mutex);
\r
1404 +SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
\r
1405 + *s, long long start_block,
\r
1409 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
1410 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
1413 + mutex_lock(&msblk->fragment_mutex);
\r
1415 + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
\r
1416 + msblk->fragment[i].block != start_block; i++);
\r
1418 + if (i == SQUASHFS_CACHED_FRAGMENTS) {
\r
1419 + for (i = msblk->next_fragment, n =
\r
1420 + SQUASHFS_CACHED_FRAGMENTS; n &&
\r
1421 + msblk->fragment[i].locked; n--, i = (i + 1) %
\r
1422 + SQUASHFS_CACHED_FRAGMENTS);
\r
1425 + wait_queue_t wait;
\r
1427 + init_waitqueue_entry(&wait, current);
\r
1428 + add_wait_queue(&msblk->fragment_wait_queue,
\r
1430 + set_current_state(TASK_UNINTERRUPTIBLE);
\r
1431 + mutex_unlock(&msblk->fragment_mutex);
\r
1433 + set_current_state(TASK_RUNNING);
\r
1434 + remove_wait_queue(&msblk->fragment_wait_queue,
\r
1438 + msblk->next_fragment = (msblk->next_fragment + 1) %
\r
1439 + SQUASHFS_CACHED_FRAGMENTS;
\r
1441 + if (msblk->fragment[i].data == NULL)
\r
1442 + if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
\r
1443 + (SQUASHFS_FILE_MAX_SIZE))) {
\r
1444 + ERROR("Failed to allocate fragment "
\r
1445 + "cache block\n");
\r
1446 + mutex_unlock(&msblk->fragment_mutex);
\r
1450 + msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
\r
1451 + msblk->fragment[i].locked = 1;
\r
1452 + mutex_unlock(&msblk->fragment_mutex);
\r
1454 + if (!(msblk->fragment[i].length = squashfs_read_data(s,
\r
1455 + msblk->fragment[i].data,
\r
1456 + start_block, length, NULL, sblk->block_size))) {
\r
1457 + ERROR("Unable to read fragment cache block "
\r
1458 + "[%llx]\n", start_block);
\r
1459 + msblk->fragment[i].locked = 0;
\r
1464 + mutex_lock(&msblk->fragment_mutex);
\r
1465 + msblk->fragment[i].block = start_block;
\r
1466 + TRACE("New fragment %d, start block %lld, locked %d\n",
\r
1467 + i, msblk->fragment[i].block,
\r
1468 + msblk->fragment[i].locked);
\r
1469 + mutex_unlock(&msblk->fragment_mutex);
\r
1473 + msblk->fragment[i].locked++;
\r
1474 + mutex_unlock(&msblk->fragment_mutex);
\r
1475 + TRACE("Got fragment %d, start block %lld, locked %d\n", i,
\r
1476 + msblk->fragment[i].block,
\r
1477 + msblk->fragment[i].locked);
\r
1481 + return &msblk->fragment[i];
\r
1488 +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
\r
1489 + struct squashfs_base_inode_header *inodeb)
\r
1491 + i->i_ino = inodeb->inode_number;
\r
1492 + i->i_mtime.tv_sec = inodeb->mtime;
\r
1493 + i->i_atime.tv_sec = inodeb->mtime;
\r
1494 + i->i_ctime.tv_sec = inodeb->mtime;
\r
1495 + i->i_uid = msblk->uid[inodeb->uid];
\r
1496 + i->i_mode = inodeb->mode;
\r
1498 + if (inodeb->guid == SQUASHFS_GUIDS)
\r
1499 + i->i_gid = i->i_uid;
\r
1501 + i->i_gid = msblk->guid[inodeb->guid];
\r
1505 +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino)
\r
1507 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
1508 + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)];
\r
1509 + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1);
\r
1510 + squashfs_inode_t inode;
\r
1512 + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino);
\r
1514 + if (msblk->swap) {
\r
1515 + squashfs_inode_t sinode;
\r
1517 + if (!squashfs_get_cached_block(s, (char *) &sinode, start, offset,
\r
1518 + sizeof(sinode), &start, &offset))
\r
1520 + SQUASHFS_SWAP_INODE_T((&inode), &sinode);
\r
1521 + } else if (!squashfs_get_cached_block(s, (char *) &inode, start, offset,
\r
1522 + sizeof(inode), &start, &offset))
\r
1525 + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode);
\r
1530 + return SQUASHFS_INVALID_BLK;
\r
1534 +static void vfs_read_inode(struct inode *i)
\r
1536 + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
\r
1537 + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino);
\r
1539 + TRACE("Entered vfs_read_inode\n");
\r
1541 + if(inode != SQUASHFS_INVALID_BLK)
\r
1542 + (msblk->read_inode)(i, inode);
\r
1546 +static struct dentry *squashfs_get_parent(struct dentry *child)
\r
1548 + struct inode *i = child->d_inode;
\r
1549 + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode);
\r
1550 + struct dentry *rv;
\r
1552 + TRACE("Entered squashfs_get_parent\n");
\r
1554 + if(parent == NULL) {
\r
1555 + rv = ERR_PTR(-EACCES);
\r
1559 + rv = d_alloc_anon(parent);
\r
1561 + rv = ERR_PTR(-ENOMEM);
\r
1568 +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number)
\r
1570 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
1571 + struct inode *i = iget_locked(s, inode_number);
\r
1573 + TRACE("Entered squashfs_iget\n");
\r
1575 + if(i && (i->i_state & I_NEW)) {
\r
1576 + (msblk->read_inode)(i, inode);
\r
1577 + unlock_new_inode(i);
\r
1584 +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode)
\r
1586 + struct super_block *s = i->i_sb;
\r
1587 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
1588 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
1589 + long long block = SQUASHFS_INODE_BLK(inode) +
\r
1590 + sblk->inode_table_start;
\r
1591 + unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
\r
1592 + long long next_block;
\r
1593 + unsigned int next_offset;
\r
1594 + union squashfs_inode_header id, sid;
\r
1595 + struct squashfs_base_inode_header *inodeb = &id.base,
\r
1596 + *sinodeb = &sid.base;
\r
1598 + TRACE("Entered squashfs_read_inode\n");
\r
1600 + if (msblk->swap) {
\r
1601 + if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
\r
1602 + offset, sizeof(*sinodeb), &next_block,
\r
1604 + goto failed_read;
\r
1605 + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
\r
1606 + sizeof(*sinodeb));
\r
1608 + if (!squashfs_get_cached_block(s, (char *) inodeb, block,
\r
1609 + offset, sizeof(*inodeb), &next_block,
\r
1611 + goto failed_read;
\r
1613 + squashfs_new_inode(msblk, i, inodeb);
\r
1615 + switch(inodeb->inode_type) {
\r
1616 + case SQUASHFS_FILE_TYPE: {
\r
1617 + unsigned int frag_size;
\r
1618 + long long frag_blk;
\r
1619 + struct squashfs_reg_inode_header *inodep = &id.reg;
\r
1620 + struct squashfs_reg_inode_header *sinodep = &sid.reg;
\r
1622 + if (msblk->swap) {
\r
1623 + if (!squashfs_get_cached_block(s, (char *)
\r
1624 + sinodep, block, offset,
\r
1625 + sizeof(*sinodep), &next_block,
\r
1627 + goto failed_read;
\r
1628 + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
\r
1630 + if (!squashfs_get_cached_block(s, (char *)
\r
1631 + inodep, block, offset,
\r
1632 + sizeof(*inodep), &next_block,
\r
1634 + goto failed_read;
\r
1636 + frag_blk = SQUASHFS_INVALID_BLK;
\r
1637 + if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
\r
1638 + !get_fragment_location(s,
\r
1639 + inodep->fragment, &frag_blk, &frag_size))
\r
1640 + goto failed_read;
\r
1643 + i->i_size = inodep->file_size;
\r
1644 + i->i_fop = &generic_ro_fops;
\r
1645 + i->i_mode |= S_IFREG;
\r
1646 + i->i_blocks = ((i->i_size - 1) >> 9) + 1;
\r
1647 + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
\r
1648 + SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
\r
1649 + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
\r
1650 + SQUASHFS_I(i)->start_block = inodep->start_block;
\r
1651 + SQUASHFS_I(i)->u.s1.block_list_start = next_block;
\r
1652 + SQUASHFS_I(i)->offset = next_offset;
\r
1653 + if (sblk->block_size > 4096)
\r
1654 + i->i_data.a_ops = &squashfs_aops;
\r
1656 + i->i_data.a_ops = &squashfs_aops_4K;
\r
1658 + TRACE("File inode %x:%x, start_block %llx, "
\r
1659 + "block_list_start %llx, offset %x\n",
\r
1660 + SQUASHFS_INODE_BLK(inode), offset,
\r
1661 + inodep->start_block, next_block,
\r
1665 + case SQUASHFS_LREG_TYPE: {
\r
1666 + unsigned int frag_size;
\r
1667 + long long frag_blk;
\r
1668 + struct squashfs_lreg_inode_header *inodep = &id.lreg;
\r
1669 + struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
\r
1671 + if (msblk->swap) {
\r
1672 + if (!squashfs_get_cached_block(s, (char *)
\r
1673 + sinodep, block, offset,
\r
1674 + sizeof(*sinodep), &next_block,
\r
1676 + goto failed_read;
\r
1677 + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
\r
1679 + if (!squashfs_get_cached_block(s, (char *)
\r
1680 + inodep, block, offset,
\r
1681 + sizeof(*inodep), &next_block,
\r
1683 + goto failed_read;
\r
1685 + frag_blk = SQUASHFS_INVALID_BLK;
\r
1686 + if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
\r
1687 + !get_fragment_location(s,
\r
1688 + inodep->fragment, &frag_blk, &frag_size))
\r
1689 + goto failed_read;
\r
1691 + i->i_nlink = inodep->nlink;
\r
1692 + i->i_size = inodep->file_size;
\r
1693 + i->i_fop = &generic_ro_fops;
\r
1694 + i->i_mode |= S_IFREG;
\r
1695 + i->i_blocks = ((i->i_size - 1) >> 9) + 1;
\r
1696 + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
\r
1697 + SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
\r
1698 + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
\r
1699 + SQUASHFS_I(i)->start_block = inodep->start_block;
\r
1700 + SQUASHFS_I(i)->u.s1.block_list_start = next_block;
\r
1701 + SQUASHFS_I(i)->offset = next_offset;
\r
1702 + if (sblk->block_size > 4096)
\r
1703 + i->i_data.a_ops = &squashfs_aops;
\r
1705 + i->i_data.a_ops = &squashfs_aops_4K;
\r
1707 + TRACE("File inode %x:%x, start_block %llx, "
\r
1708 + "block_list_start %llx, offset %x\n",
\r
1709 + SQUASHFS_INODE_BLK(inode), offset,
\r
1710 + inodep->start_block, next_block,
\r
1714 + case SQUASHFS_DIR_TYPE: {
\r
1715 + struct squashfs_dir_inode_header *inodep = &id.dir;
\r
1716 + struct squashfs_dir_inode_header *sinodep = &sid.dir;
\r
1718 + if (msblk->swap) {
\r
1719 + if (!squashfs_get_cached_block(s, (char *)
\r
1720 + sinodep, block, offset,
\r
1721 + sizeof(*sinodep), &next_block,
\r
1723 + goto failed_read;
\r
1724 + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
\r
1726 + if (!squashfs_get_cached_block(s, (char *)
\r
1727 + inodep, block, offset,
\r
1728 + sizeof(*inodep), &next_block,
\r
1730 + goto failed_read;
\r
1732 + i->i_nlink = inodep->nlink;
\r
1733 + i->i_size = inodep->file_size;
\r
1734 + i->i_op = &squashfs_dir_inode_ops;
\r
1735 + i->i_fop = &squashfs_dir_ops;
\r
1736 + i->i_mode |= S_IFDIR;
\r
1737 + SQUASHFS_I(i)->start_block = inodep->start_block;
\r
1738 + SQUASHFS_I(i)->offset = inodep->offset;
\r
1739 + SQUASHFS_I(i)->u.s2.directory_index_count = 0;
\r
1740 + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
\r
1742 + TRACE("Directory inode %x:%x, start_block %x, offset "
\r
1743 + "%x\n", SQUASHFS_INODE_BLK(inode),
\r
1744 + offset, inodep->start_block,
\r
1745 + inodep->offset);
\r
1748 + case SQUASHFS_LDIR_TYPE: {
\r
1749 + struct squashfs_ldir_inode_header *inodep = &id.ldir;
\r
1750 + struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
\r
1752 + if (msblk->swap) {
\r
1753 + if (!squashfs_get_cached_block(s, (char *)
\r
1754 + sinodep, block, offset,
\r
1755 + sizeof(*sinodep), &next_block,
\r
1757 + goto failed_read;
\r
1758 + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
\r
1761 + if (!squashfs_get_cached_block(s, (char *)
\r
1762 + inodep, block, offset,
\r
1763 + sizeof(*inodep), &next_block,
\r
1765 + goto failed_read;
\r
1767 + i->i_nlink = inodep->nlink;
\r
1768 + i->i_size = inodep->file_size;
\r
1769 + i->i_op = &squashfs_dir_inode_ops;
\r
1770 + i->i_fop = &squashfs_dir_ops;
\r
1771 + i->i_mode |= S_IFDIR;
\r
1772 + SQUASHFS_I(i)->start_block = inodep->start_block;
\r
1773 + SQUASHFS_I(i)->offset = inodep->offset;
\r
1774 + SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
\r
1775 + SQUASHFS_I(i)->u.s2.directory_index_offset =
\r
1777 + SQUASHFS_I(i)->u.s2.directory_index_count =
\r
1778 + inodep->i_count;
\r
1779 + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
\r
1781 + TRACE("Long directory inode %x:%x, start_block %x, "
\r
1783 + SQUASHFS_INODE_BLK(inode), offset,
\r
1784 + inodep->start_block, inodep->offset);
\r
1787 + case SQUASHFS_SYMLINK_TYPE: {
\r
1788 + struct squashfs_symlink_inode_header *inodep =
\r
1790 + struct squashfs_symlink_inode_header *sinodep =
\r
1793 + if (msblk->swap) {
\r
1794 + if (!squashfs_get_cached_block(s, (char *)
\r
1795 + sinodep, block, offset,
\r
1796 + sizeof(*sinodep), &next_block,
\r
1798 + goto failed_read;
\r
1799 + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
\r
1802 + if (!squashfs_get_cached_block(s, (char *)
\r
1803 + inodep, block, offset,
\r
1804 + sizeof(*inodep), &next_block,
\r
1806 + goto failed_read;
\r
1808 + i->i_nlink = inodep->nlink;
\r
1809 + i->i_size = inodep->symlink_size;
\r
1810 + i->i_op = &page_symlink_inode_operations;
\r
1811 + i->i_data.a_ops = &squashfs_symlink_aops;
\r
1812 + i->i_mode |= S_IFLNK;
\r
1813 + SQUASHFS_I(i)->start_block = next_block;
\r
1814 + SQUASHFS_I(i)->offset = next_offset;
\r
1816 + TRACE("Symbolic link inode %x:%x, start_block %llx, "
\r
1818 + SQUASHFS_INODE_BLK(inode), offset,
\r
1819 + next_block, next_offset);
\r
1822 + case SQUASHFS_BLKDEV_TYPE:
\r
1823 + case SQUASHFS_CHRDEV_TYPE: {
\r
1824 + struct squashfs_dev_inode_header *inodep = &id.dev;
\r
1825 + struct squashfs_dev_inode_header *sinodep = &sid.dev;
\r
1827 + if (msblk->swap) {
\r
1828 + if (!squashfs_get_cached_block(s, (char *)
\r
1829 + sinodep, block, offset,
\r
1830 + sizeof(*sinodep), &next_block,
\r
1832 + goto failed_read;
\r
1833 + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
\r
1835 + if (!squashfs_get_cached_block(s, (char *)
\r
1836 + inodep, block, offset,
\r
1837 + sizeof(*inodep), &next_block,
\r
1839 + goto failed_read;
\r
1841 + i->i_nlink = inodep->nlink;
\r
1842 + i->i_mode |= (inodeb->inode_type ==
\r
1843 + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
\r
1845 + init_special_inode(i, i->i_mode,
\r
1846 + old_decode_dev(inodep->rdev));
\r
1848 + TRACE("Device inode %x:%x, rdev %x\n",
\r
1849 + SQUASHFS_INODE_BLK(inode), offset,
\r
1853 + case SQUASHFS_FIFO_TYPE:
\r
1854 + case SQUASHFS_SOCKET_TYPE: {
\r
1855 + struct squashfs_ipc_inode_header *inodep = &id.ipc;
\r
1856 + struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
\r
1858 + if (msblk->swap) {
\r
1859 + if (!squashfs_get_cached_block(s, (char *)
\r
1860 + sinodep, block, offset,
\r
1861 + sizeof(*sinodep), &next_block,
\r
1863 + goto failed_read;
\r
1864 + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
\r
1866 + if (!squashfs_get_cached_block(s, (char *)
\r
1867 + inodep, block, offset,
\r
1868 + sizeof(*inodep), &next_block,
\r
1870 + goto failed_read;
\r
1872 + i->i_nlink = inodep->nlink;
\r
1873 + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
\r
1874 + ? S_IFIFO : S_IFSOCK;
\r
1875 + init_special_inode(i, i->i_mode, 0);
\r
1879 + ERROR("Unknown inode type %d in squashfs_iget!\n",
\r
1880 + inodeb->inode_type);
\r
1881 + goto failed_read1;
\r
1887 + ERROR("Unable to read inode [%llx:%x]\n", block, offset);
\r
1890 + make_bad_inode(i);
\r
1895 +static int read_inode_lookup_table(struct super_block *s)
\r
1897 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
1898 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
1899 + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes);
\r
1901 + TRACE("In read_inode_lookup_table, length %d\n", length);
\r
1903 + /* Allocate inode lookup table */
\r
1904 + if (!(msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL))) {
\r
1905 + ERROR("Failed to allocate inode lookup table\n");
\r
1909 + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table,
\r
1910 + sblk->lookup_table_start, length |
\r
1911 + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
\r
1912 + ERROR("unable to read inode lookup table\n");
\r
1916 + if (msblk->swap) {
\r
1918 + long long block;
\r
1920 + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) {
\r
1921 + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block),
\r
1922 + &msblk->inode_lookup_table[i], 1);
\r
1923 + msblk->inode_lookup_table[i] = block;
\r
1931 +static int read_fragment_index_table(struct super_block *s)
\r
1933 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
1934 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
1935 + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments);
\r
1940 + /* Allocate fragment index table */
\r
1941 + if (!(msblk->fragment_index = kmalloc(length, GFP_KERNEL))) {
\r
1942 + ERROR("Failed to allocate fragment index table\n");
\r
1946 + if (!squashfs_read_data(s, (char *) msblk->fragment_index,
\r
1947 + sblk->fragment_table_start, length |
\r
1948 + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
\r
1949 + ERROR("unable to read fragment index table\n");
\r
1953 + if (msblk->swap) {
\r
1955 + long long fragment;
\r
1957 + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) {
\r
1958 + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
\r
1959 + &msblk->fragment_index[i], 1);
\r
1960 + msblk->fragment_index[i] = fragment;
\r
1968 +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
\r
1970 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
1972 + msblk->read_inode = squashfs_read_inode;
\r
1973 + msblk->read_blocklist = read_blocklist;
\r
1974 + msblk->read_fragment_index_table = read_fragment_index_table;
\r
1976 + if (sblk->s_major == 1) {
\r
1977 + if (!squashfs_1_0_supported(msblk)) {
\r
1978 + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
\r
1979 + "are unsupported\n");
\r
1980 + SERROR("Please recompile with "
\r
1981 + "Squashfs 1.0 support enabled\n");
\r
1984 + } else if (sblk->s_major == 2) {
\r
1985 + if (!squashfs_2_0_supported(msblk)) {
\r
1986 + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
\r
1987 + "are unsupported\n");
\r
1988 + SERROR("Please recompile with "
\r
1989 + "Squashfs 2.0 support enabled\n");
\r
1992 + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
\r
1993 + SQUASHFS_MINOR) {
\r
1994 + SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
\r
1995 + "filesystem\n", sblk->s_major, sblk->s_minor);
\r
1996 + SERROR("Please update your kernel\n");
\r
2004 +static int squashfs_fill_super(struct super_block *s, void *data, int silent)
\r
2006 + struct squashfs_sb_info *msblk;
\r
2007 + struct squashfs_super_block *sblk;
\r
2009 + char b[BDEVNAME_SIZE];
\r
2010 + struct inode *root;
\r
2013 + TRACE("Entered squashfs_read_superblock\n");
\r
2016 + if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),
\r
2018 + ERROR("Failed to allocate superblock\n");
\r
2021 + label = &&out_fsinfo;
\r
2022 + memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));
\r
2023 + msblk = s->s_fs_info;
\r
2024 + sblk = &msblk->sblk;
\r
2026 + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);
\r
2027 + msblk->devblksize_log2 = ffz(~msblk->devblksize);
\r
2029 + //mutex_init(&msblk->read_data_mutex);
\r
2030 + mutex_init(&msblk->read_page_mutex);
\r
2031 + mutex_init(&msblk->block_cache_mutex);
\r
2032 + mutex_init(&msblk->fragment_mutex);
\r
2033 + mutex_init(&msblk->meta_index_mutex);
\r
2035 + init_waitqueue_head(&msblk->waitq);
\r
2036 + init_waitqueue_head(&msblk->fragment_wait_queue);
\r
2039 + sblk->bytes_used = sizeof(struct squashfs_super_block);
\r
2040 + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
\r
2041 + sizeof(struct squashfs_super_block) |
\r
2042 + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) {
\r
2043 + SERROR("unable to read superblock\n");
\r
2047 + /* Check it is a SQUASHFS superblock */
\r
2048 + s->s_magic = sblk->s_magic;
\r
2049 + msblk->swap = 0;
\r
2050 + dpri("magic 0x%x\n", sblk->s_magic);
\r
2051 + switch (sblk->s_magic) {
\r
2052 + struct squashfs_super_block ssblk;
\r
2054 + case SQUASHFS_MAGIC_SWAP:
\r
2056 + case SQUASHFS_MAGIC_LZMA_SWAP:
\r
2057 + WARNING("Mounting a different endian SQUASHFS "
\r
2058 + "filesystem on %s\n", bdevname(s->s_bdev, b));
\r
2060 + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
\r
2061 + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
\r
2062 + msblk->swap = 1;
\r
2064 + case SQUASHFS_MAGIC:
\r
2065 + case SQUASHFS_MAGIC_LZMA:
\r
2068 + SERROR("Can't find a SQUASHFS superblock on %s\n",
\r
2069 + bdevname(s->s_bdev, b));
\r
2074 + struct sqlzma *p;
\r
2075 + dpri("block_size %d\n", sblk->block_size);
\r
2076 + BUG_ON(sblk->block_size > sizeof(p->read_data));
\r
2079 + /* Check the MAJOR & MINOR versions */
\r
2081 + if(!supported_squashfs_filesystem(msblk, silent))
\r
2084 + /* Check the filesystem does not extend beyond the end of the
\r
2086 + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode))
\r
2089 + /* Check the root inode for sanity */
\r
2090 + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE)
\r
2093 + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
\r
2094 + TRACE("Inodes are %scompressed\n",
\r
2095 + SQUASHFS_UNCOMPRESSED_INODES
\r
2096 + (sblk->flags) ? "un" : "");
\r
2097 + TRACE("Data is %scompressed\n",
\r
2098 + SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
\r
2100 + TRACE("Check data is %s present in the filesystem\n",
\r
2101 + SQUASHFS_CHECK_DATA(sblk->flags) ?
\r
2103 + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
\r
2104 + TRACE("Block size %d\n", sblk->block_size);
\r
2105 + TRACE("Number of inodes %d\n", sblk->inodes);
\r
2106 + if (sblk->s_major > 1)
\r
2107 + TRACE("Number of fragments %d\n", sblk->fragments);
\r
2108 + TRACE("Number of uids %d\n", sblk->no_uids);
\r
2109 + TRACE("Number of gids %d\n", sblk->no_guids);
\r
2110 + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
\r
2111 + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
\r
2112 + if (sblk->s_major > 1)
\r
2113 + TRACE("sblk->fragment_table_start %llx\n",
\r
2114 + sblk->fragment_table_start);
\r
2115 + TRACE("sblk->uid_start %llx\n", sblk->uid_start);
\r
2117 + s->s_flags |= MS_RDONLY;
\r
2118 + s->s_op = &squashfs_super_ops;
\r
2120 + /* Init inode_table block pointer array */
\r
2122 + if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
\r
2123 + SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
\r
2124 + ERROR("Failed to allocate block cache\n");
\r
2127 + label = &&out_block_cache;
\r
2129 + for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
\r
2130 + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
\r
2132 + msblk->next_cache = 0;
\r
2134 + /* Allocate read_page block */
\r
2135 + if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
\r
2136 + ERROR("Failed to allocate read_page block\n");
\r
2139 + label = &&out_read_page;
\r
2141 + /* Allocate uid and gid tables */
\r
2142 + if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
\r
2143 + sizeof(unsigned int), GFP_KERNEL))) {
\r
2144 + ERROR("Failed to allocate uid/gid table\n");
\r
2147 + label = &&out_uid;
\r
2148 + msblk->guid = msblk->uid + sblk->no_uids;
\r
2150 + dpri("swap %d\n", msblk->swap);
\r
2152 + if (msblk->swap) {
\r
2153 + unsigned int suid[sblk->no_uids + sblk->no_guids];
\r
2155 + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
\r
2156 + ((sblk->no_uids + sblk->no_guids) *
\r
2157 + sizeof(unsigned int)) |
\r
2158 + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {
\r
2159 + ERROR("unable to read uid/gid table\n");
\r
2163 + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
\r
2164 + sblk->no_guids), (sizeof(unsigned int) * 8));
\r
2166 + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
\r
2167 + ((sblk->no_uids + sblk->no_guids) *
\r
2168 + sizeof(unsigned int)) |
\r
2169 + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {
\r
2170 + ERROR("unable to read uid/gid table\n");
\r
2175 + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
\r
2176 + goto allocate_root;
\r
2179 + if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
\r
2180 + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
\r
2181 + ERROR("Failed to allocate fragment block cache\n");
\r
2184 + label = &&out_fragment;
\r
2186 + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
\r
2187 + msblk->fragment[i].locked = 0;
\r
2188 + msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
\r
2189 + msblk->fragment[i].data = NULL;
\r
2192 + msblk->next_fragment = 0;
\r
2194 + /* Allocate and read fragment index table */
\r
2195 + if (msblk->read_fragment_index_table(s) == 0)
\r
2198 + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK)
\r
2199 + goto allocate_root;
\r
2201 + /* Allocate and read inode lookup table */
\r
2202 + if (read_inode_lookup_table(s) == 0)
\r
2203 + goto failed_mount;
\r
2205 + s->s_op = &squashfs_export_super_ops;
\r
2206 + s->s_export_op = &squashfs_export_ops;
\r
2209 + dpri("alloate_root\n");
\r
2210 + root = new_inode(s);
\r
2211 + if ((msblk->read_inode)(root, sblk->root_inode) == 0) {
\r
2213 + goto failed_mount;
\r
2215 + insert_inode_hash(root);
\r
2217 + if ((s->s_root = d_alloc_root(root)) == NULL) {
\r
2218 + ERROR("Root inode create failed\n");
\r
2220 + goto failed_mount;
\r
2223 + TRACE("Leaving squashfs_read_super\n");
\r
2227 + kfree(msblk->inode_lookup_table);
\r
2228 + kfree(msblk->fragment_index);
\r
2229 + kfree(msblk->fragment_index_2);
\r
2231 + kfree(msblk->fragment);
\r
2233 + kfree(msblk->uid);
\r
2235 + kfree(msblk->read_page);
\r
2236 + out_block_cache:
\r
2237 + kfree(msblk->block_cache);
\r
2239 + kfree(s->s_fs_info);
\r
2240 + s->s_fs_info = NULL;
\r
2246 +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
\r
2248 + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
\r
2249 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
2251 + TRACE("Entered squashfs_statfs\n");
\r
2253 + buf->f_type = sblk->s_magic;
\r
2254 + buf->f_bsize = sblk->block_size;
\r
2255 + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
\r
2256 + buf->f_bfree = buf->f_bavail = 0;
\r
2257 + buf->f_files = sblk->inodes;
\r
2258 + buf->f_ffree = 0;
\r
2259 + buf->f_namelen = SQUASHFS_NAME_LEN;
\r
2265 +static int squashfs_symlink_readpage(struct file *file, struct page *page)
\r
2267 + struct inode *inode = page->mapping->host;
\r
2268 + int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
\r
2269 + long long block = SQUASHFS_I(inode)->start_block;
\r
2270 + int offset = SQUASHFS_I(inode)->offset;
\r
2271 + void *pageaddr = kmap(page);
\r
2273 + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
\r
2274 + "%llx, offset %x\n", page->index,
\r
2275 + SQUASHFS_I(inode)->start_block,
\r
2276 + SQUASHFS_I(inode)->offset);
\r
2278 + for (length = 0; length < index; length += bytes) {
\r
2279 + if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
\r
2280 + block, offset, PAGE_CACHE_SIZE, &block,
\r
2282 + ERROR("Unable to read symbolic link [%llx:%x]\n", block,
\r
2288 + if (length != index) {
\r
2289 + ERROR("(squashfs_symlink_readpage) length != index\n");
\r
2294 + bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
\r
2295 + i_size_read(inode) - length;
\r
2297 + if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
\r
2298 + offset, bytes, &block, &offset)))
\r
2299 + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
\r
2302 + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
\r
2304 + flush_dcache_page(page);
\r
2305 + SetPageUptodate(page);
\r
2306 + unlock_page(page);
\r
2312 +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
\r
2314 + struct meta_index *meta = NULL;
\r
2315 + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
\r
2318 + mutex_lock(&msblk->meta_index_mutex);
\r
2320 + TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
\r
2322 + if(msblk->meta_index == NULL)
\r
2323 + goto not_allocated;
\r
2325 + for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
\r
2326 + if (msblk->meta_index[i].inode_number == inode->i_ino &&
\r
2327 + msblk->meta_index[i].offset >= offset &&
\r
2328 + msblk->meta_index[i].offset <= index &&
\r
2329 + msblk->meta_index[i].locked == 0) {
\r
2330 + TRACE("locate_meta_index: entry %d, offset %d\n", i,
\r
2331 + msblk->meta_index[i].offset);
\r
2332 + meta = &msblk->meta_index[i];
\r
2333 + offset = meta->offset;
\r
2337 + meta->locked = 1;
\r
2340 + mutex_unlock(&msblk->meta_index_mutex);
\r
2346 +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
\r
2348 + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
\r
2349 + struct meta_index *meta = NULL;
\r
2352 + mutex_lock(&msblk->meta_index_mutex);
\r
2354 + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
\r
2356 + if(msblk->meta_index == NULL) {
\r
2357 + if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
\r
2358 + SQUASHFS_META_NUMBER, GFP_KERNEL))) {
\r
2359 + ERROR("Failed to allocate meta_index\n");
\r
2362 + for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
\r
2363 + msblk->meta_index[i].inode_number = 0;
\r
2364 + msblk->meta_index[i].locked = 0;
\r
2366 + msblk->next_meta_index = 0;
\r
2369 + for(i = SQUASHFS_META_NUMBER; i &&
\r
2370 + msblk->meta_index[msblk->next_meta_index].locked; i --)
\r
2371 + msblk->next_meta_index = (msblk->next_meta_index + 1) %
\r
2372 + SQUASHFS_META_NUMBER;
\r
2375 + TRACE("empty_meta_index: failed!\n");
\r
2379 + TRACE("empty_meta_index: returned meta entry %d, %p\n",
\r
2380 + msblk->next_meta_index,
\r
2381 + &msblk->meta_index[msblk->next_meta_index]);
\r
2383 + meta = &msblk->meta_index[msblk->next_meta_index];
\r
2384 + msblk->next_meta_index = (msblk->next_meta_index + 1) %
\r
2385 + SQUASHFS_META_NUMBER;
\r
2387 + meta->inode_number = inode->i_ino;
\r
2388 + meta->offset = offset;
\r
2389 + meta->skip = skip;
\r
2390 + meta->entries = 0;
\r
2391 + meta->locked = 1;
\r
2394 + mutex_unlock(&msblk->meta_index_mutex);
\r
2399 +void release_meta_index(struct inode *inode, struct meta_index *meta)
\r
2401 + meta->locked = 0;
\r
2406 +static int read_block_index(struct super_block *s, int blocks, char *block_list,
\r
2407 + long long *start_block, int *offset)
\r
2409 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
2410 + unsigned int *block_listp;
\r
2413 + if (msblk->swap) {
\r
2414 + char sblock_list[blocks << 2];
\r
2416 + if (!squashfs_get_cached_block(s, sblock_list, *start_block,
\r
2417 + *offset, blocks << 2, start_block, offset)) {
\r
2418 + ERROR("Unable to read block list [%llx:%x]\n",
\r
2419 + *start_block, *offset);
\r
2422 + SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
\r
2423 + ((unsigned int *)sblock_list), blocks);
\r
2425 + if (!squashfs_get_cached_block(s, block_list, *start_block,
\r
2426 + *offset, blocks << 2, start_block, offset)) {
\r
2427 + ERROR("Unable to read block list [%llx:%x]\n",
\r
2428 + *start_block, *offset);
\r
2432 + for (block_listp = (unsigned int *) block_list; blocks;
\r
2433 + block_listp++, blocks --)
\r
2434 + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
\r
2445 +static inline int calculate_skip(int blocks) {
\r
2446 + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
\r
2447 + return skip >= 7 ? 7 : skip + 1;
\r
2451 +static int get_meta_index(struct inode *inode, int index,
\r
2452 + long long *index_block, int *index_offset,
\r
2453 + long long *data_block, char *block_list)
\r
2455 + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
\r
2456 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
2457 + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
\r
2459 + struct meta_index *meta;
\r
2460 + struct meta_entry *meta_entry;
\r
2461 + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
\r
2462 + int cur_offset = SQUASHFS_I(inode)->offset;
\r
2463 + long long cur_data_block = SQUASHFS_I(inode)->start_block;
\r
2466 + index /= SQUASHFS_META_INDEXES * skip;
\r
2468 + while ( offset < index ) {
\r
2469 + meta = locate_meta_index(inode, index, offset + 1);
\r
2471 + if (meta == NULL) {
\r
2472 + if ((meta = empty_meta_index(inode, offset + 1,
\r
2476 + if(meta->entries == 0)
\r
2478 + offset = index < meta->offset + meta->entries ? index :
\r
2479 + meta->offset + meta->entries - 1;
\r
2480 + meta_entry = &meta->meta_entry[offset - meta->offset];
\r
2481 + cur_index_block = meta_entry->index_block + sblk->inode_table_start;
\r
2482 + cur_offset = meta_entry->offset;
\r
2483 + cur_data_block = meta_entry->data_block;
\r
2484 + TRACE("get_meta_index: offset %d, meta->offset %d, "
\r
2485 + "meta->entries %d\n", offset, meta->offset,
\r
2487 + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
\r
2488 + " data_block 0x%llx\n", cur_index_block,
\r
2489 + cur_offset, cur_data_block);
\r
2492 + for (i = meta->offset + meta->entries; i <= index &&
\r
2493 + i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
\r
2494 + int blocks = skip * SQUASHFS_META_INDEXES;
\r
2496 + while (blocks) {
\r
2497 + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
\r
2499 + int res = read_block_index(inode->i_sb, block,
\r
2500 + block_list, &cur_index_block,
\r
2506 + cur_data_block += res;
\r
2507 + blocks -= block;
\r
2510 + meta_entry = &meta->meta_entry[i - meta->offset];
\r
2511 + meta_entry->index_block = cur_index_block - sblk->inode_table_start;
\r
2512 + meta_entry->offset = cur_offset;
\r
2513 + meta_entry->data_block = cur_data_block;
\r
2514 + meta->entries ++;
\r
2518 + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
\r
2519 + meta->offset, meta->entries);
\r
2521 + release_meta_index(inode, meta);
\r
2525 + *index_block = cur_index_block;
\r
2526 + *index_offset = cur_offset;
\r
2527 + *data_block = cur_data_block;
\r
2529 + return offset * SQUASHFS_META_INDEXES * skip;
\r
2532 + release_meta_index(inode, meta);
\r
2537 +static long long read_blocklist(struct inode *inode, int index,
\r
2538 + int readahead_blks, char *block_list,
\r
2539 + unsigned short **block_p, unsigned int *bsize)
\r
2541 + long long block_ptr;
\r
2543 + long long block;
\r
2544 + int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
\r
2547 + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
\r
2548 + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
\r
2556 + while ( index ) {
\r
2557 + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
\r
2558 + int res = read_block_index(inode->i_sb, blocks, block_list,
\r
2559 + &block_ptr, &offset);
\r
2563 + index -= blocks;
\r
2566 + if (read_block_index(inode->i_sb, 1, block_list,
\r
2567 + &block_ptr, &offset) == -1)
\r
2569 + *bsize = *((unsigned int *) block_list);
\r
2578 +static int squashfs_readpage(struct file *file, struct page *page)
\r
2580 + struct inode *inode = page->mapping->host;
\r
2581 + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
\r
2582 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
2583 + unsigned char *block_list;
\r
2584 + long long block;
\r
2585 + unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
\r
2586 + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
\r
2588 + struct squashfs_fragment_cache *fragment = NULL;
\r
2589 + char *data_ptr = msblk->read_page;
\r
2591 + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
\r
2592 + int start_index = page->index & ~mask;
\r
2593 + int end_index = start_index | mask;
\r
2595 + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
\r
2597 + SQUASHFS_I(inode)->start_block);
\r
2599 + if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
\r
2600 + ERROR("Failed to allocate block_list\n");
\r
2604 + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
\r
2605 + PAGE_CACHE_SHIFT))
\r
2608 + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
\r
2609 + || index < (i_size_read(inode) >>
\r
2610 + sblk->block_log)) {
\r
2611 + if ((block = (msblk->read_blocklist)(inode, index, 1,
\r
2612 + block_list, NULL, &bsize)) == 0)
\r
2615 + mutex_lock(&msblk->read_page_mutex);
\r
2617 + if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
\r
2618 + block, bsize, NULL, sblk->block_size))) {
\r
2619 + ERROR("Unable to read page, block %llx, size %x\n", block,
\r
2621 + mutex_unlock(&msblk->read_page_mutex);
\r
2625 + if ((fragment = get_cached_fragment(inode->i_sb,
\r
2626 + SQUASHFS_I(inode)->
\r
2627 + u.s1.fragment_start_block,
\r
2628 + SQUASHFS_I(inode)->u.s1.fragment_size))
\r
2630 + ERROR("Unable to read page, block %llx, size %x\n",
\r
2631 + SQUASHFS_I(inode)->
\r
2632 + u.s1.fragment_start_block,
\r
2633 + (int) SQUASHFS_I(inode)->
\r
2634 + u.s1.fragment_size);
\r
2637 + bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
\r
2638 + (i_size_read(inode) & (sblk->block_size
\r
2640 + byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
\r
2641 + data_ptr = fragment->data;
\r
2644 + for (i = start_index; i <= end_index && byte_offset < bytes;
\r
2645 + i++, byte_offset += PAGE_CACHE_SIZE) {
\r
2646 + struct page *push_page;
\r
2647 + int avail = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
\r
2648 + PAGE_CACHE_SIZE : bytes - byte_offset;
\r
2650 + TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
\r
2651 + bytes, i, byte_offset, avail);
\r
2653 + push_page = (i == page->index) ? page :
\r
2654 + grab_cache_page_nowait(page->mapping, i);
\r
2659 + if (PageUptodate(push_page))
\r
2662 + pageaddr = kmap_atomic(push_page, KM_USER0);
\r
2663 + memcpy(pageaddr, data_ptr + byte_offset, avail);
\r
2664 + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);
\r
2665 + kunmap_atomic(pageaddr, KM_USER0);
\r
2666 + flush_dcache_page(push_page);
\r
2667 + SetPageUptodate(push_page);
\r
2669 + unlock_page(push_page);
\r
2670 + if(i != page->index)
\r
2671 + page_cache_release(push_page);
\r
2674 + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
\r
2675 + || index < (i_size_read(inode) >>
\r
2676 + sblk->block_log))
\r
2677 + mutex_unlock(&msblk->read_page_mutex);
\r
2679 + release_cached_fragment(msblk, fragment);
\r
2681 + kfree(block_list);
\r
2685 + pageaddr = kmap_atomic(page, KM_USER0);
\r
2686 + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
\r
2687 + kunmap_atomic(pageaddr, KM_USER0);
\r
2688 + flush_dcache_page(page);
\r
2689 + SetPageUptodate(page);
\r
2690 + unlock_page(page);
\r
2692 + kfree(block_list);
\r
2697 +static int squashfs_readpage4K(struct file *file, struct page *page)
\r
2699 + struct inode *inode = page->mapping->host;
\r
2700 + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
\r
2701 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
2702 + unsigned char *block_list;
\r
2703 + long long block;
\r
2704 + unsigned int bsize, bytes = 0;
\r
2707 + TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
\r
2709 + SQUASHFS_I(inode)->start_block);
\r
2711 + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
\r
2712 + PAGE_CACHE_SHIFT)) {
\r
2713 + block_list = NULL;
\r
2717 + if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
\r
2718 + ERROR("Failed to allocate block_list\n");
\r
2722 + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
\r
2723 + || page->index < (i_size_read(inode) >>
\r
2724 + sblk->block_log)) {
\r
2725 + block = (msblk->read_blocklist)(inode, page->index, 1,
\r
2726 + block_list, NULL, &bsize);
\r
2730 + mutex_lock(&msblk->read_page_mutex);
\r
2731 + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
\r
2732 + bsize, NULL, sblk->block_size);
\r
2734 + pageaddr = kmap_atomic(page, KM_USER0);
\r
2735 + memcpy(pageaddr, msblk->read_page, bytes);
\r
2736 + kunmap_atomic(pageaddr, KM_USER0);
\r
2738 + ERROR("Unable to read page, block %llx, size %x\n",
\r
2740 + mutex_unlock(&msblk->read_page_mutex);
\r
2742 + struct squashfs_fragment_cache *fragment =
\r
2743 + get_cached_fragment(inode->i_sb,
\r
2744 + SQUASHFS_I(inode)->
\r
2745 + u.s1.fragment_start_block,
\r
2746 + SQUASHFS_I(inode)-> u.s1.fragment_size);
\r
2748 + bytes = i_size_read(inode) & (sblk->block_size - 1);
\r
2749 + pageaddr = kmap_atomic(page, KM_USER0);
\r
2750 + memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
\r
2751 + u.s1.fragment_offset, bytes);
\r
2752 + kunmap_atomic(pageaddr, KM_USER0);
\r
2753 + release_cached_fragment(msblk, fragment);
\r
2755 + ERROR("Unable to read page, block %llx, size %x\n",
\r
2756 + SQUASHFS_I(inode)->
\r
2757 + u.s1.fragment_start_block, (int)
\r
2758 + SQUASHFS_I(inode)-> u.s1.fragment_size);
\r
2762 + pageaddr = kmap_atomic(page, KM_USER0);
\r
2763 + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
\r
2764 + kunmap_atomic(pageaddr, KM_USER0);
\r
2765 + flush_dcache_page(page);
\r
2766 + SetPageUptodate(page);
\r
2767 + unlock_page(page);
\r
2769 + kfree(block_list);
\r
2774 +static int get_dir_index_using_offset(struct super_block *s, long long
\r
2775 + *next_block, unsigned int *next_offset,
\r
2776 + long long index_start,
\r
2777 + unsigned int index_offset, int i_count,
\r
2778 + long long f_pos)
\r
2780 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
2781 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
2782 + int i, length = 0;
\r
2783 + struct squashfs_dir_index index;
\r
2785 + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
\r
2786 + i_count, (unsigned int) f_pos);
\r
2792 + for (i = 0; i < i_count; i++) {
\r
2793 + if (msblk->swap) {
\r
2794 + struct squashfs_dir_index sindex;
\r
2795 + squashfs_get_cached_block(s, (char *) &sindex,
\r
2796 + index_start, index_offset,
\r
2797 + sizeof(sindex), &index_start,
\r
2799 + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
\r
2801 + squashfs_get_cached_block(s, (char *) &index,
\r
2802 + index_start, index_offset,
\r
2803 + sizeof(index), &index_start,
\r
2806 + if (index.index > f_pos)
\r
2809 + squashfs_get_cached_block(s, NULL, index_start, index_offset,
\r
2810 + index.size + 1, &index_start,
\r
2813 + length = index.index;
\r
2814 + *next_block = index.start_block + sblk->directory_table_start;
\r
2817 + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
\r
2820 + return length + 3;
\r
2824 +static int get_dir_index_using_name(struct super_block *s, long long
\r
2825 + *next_block, unsigned int *next_offset,
\r
2826 + long long index_start,
\r
2827 + unsigned int index_offset, int i_count,
\r
2828 + const char *name, int size)
\r
2830 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
2831 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
2832 + int i, length = 0;
\r
2833 + struct squashfs_dir_index *index;
\r
2836 + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
\r
2838 + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
\r
2839 + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
\r
2840 + ERROR("Failed to allocate squashfs_dir_index\n");
\r
2844 + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1);
\r
2845 + strncpy(str, name, size);
\r
2846 + str[size] = '\0';
\r
2848 + for (i = 0; i < i_count; i++) {
\r
2849 + if (msblk->swap) {
\r
2850 + struct squashfs_dir_index sindex;
\r
2851 + squashfs_get_cached_block(s, (char *) &sindex,
\r
2852 + index_start, index_offset,
\r
2853 + sizeof(sindex), &index_start,
\r
2855 + SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
\r
2857 + squashfs_get_cached_block(s, (char *) index,
\r
2858 + index_start, index_offset,
\r
2859 + sizeof(struct squashfs_dir_index),
\r
2860 + &index_start, &index_offset);
\r
2862 + squashfs_get_cached_block(s, index->name, index_start,
\r
2863 + index_offset, index->size + 1,
\r
2864 + &index_start, &index_offset);
\r
2866 + index->name[index->size + 1] = '\0';
\r
2868 + if (strcmp(index->name, str) > 0)
\r
2871 + length = index->index;
\r
2872 + *next_block = index->start_block + sblk->directory_table_start;
\r
2875 + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
\r
2878 + return length + 3;
\r
2882 +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
\r
2884 + struct inode *i = file->f_dentry->d_inode;
\r
2885 + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
\r
2886 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
2887 + long long next_block = SQUASHFS_I(i)->start_block +
\r
2888 + sblk->directory_table_start;
\r
2889 + int next_offset = SQUASHFS_I(i)->offset, length = 0,
\r
2891 + struct squashfs_dir_header dirh;
\r
2892 + struct squashfs_dir_entry *dire;
\r
2894 + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
\r
2896 + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
\r
2897 + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
\r
2898 + ERROR("Failed to allocate squashfs_dir_entry\n");
\r
2902 + while(file->f_pos < 3) {
\r
2904 + int size, i_ino;
\r
2906 + if(file->f_pos == 0) {
\r
2909 + i_ino = i->i_ino;
\r
2913 + i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
\r
2915 + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
\r
2916 + (unsigned int) dirent, name, size, (int)
\r
2917 + file->f_pos, i_ino,
\r
2918 + squashfs_filetype_table[1]);
\r
2920 + if (filldir(dirent, name, size,
\r
2921 + file->f_pos, i_ino,
\r
2922 + squashfs_filetype_table[1]) < 0) {
\r
2923 + TRACE("Filldir returned less than 0\n");
\r
2926 + file->f_pos += size;
\r
2929 + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
\r
2930 + SQUASHFS_I(i)->u.s2.directory_index_start,
\r
2931 + SQUASHFS_I(i)->u.s2.directory_index_offset,
\r
2932 + SQUASHFS_I(i)->u.s2.directory_index_count,
\r
2935 + while (length < i_size_read(i)) {
\r
2936 + /* read directory header */
\r
2937 + if (msblk->swap) {
\r
2938 + struct squashfs_dir_header sdirh;
\r
2940 + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
\r
2941 + next_block, next_offset, sizeof(sdirh),
\r
2942 + &next_block, &next_offset))
\r
2943 + goto failed_read;
\r
2945 + length += sizeof(sdirh);
\r
2946 + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
\r
2948 + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
\r
2949 + next_block, next_offset, sizeof(dirh),
\r
2950 + &next_block, &next_offset))
\r
2951 + goto failed_read;
\r
2953 + length += sizeof(dirh);
\r
2956 + dir_count = dirh.count + 1;
\r
2957 + while (dir_count--) {
\r
2958 + if (msblk->swap) {
\r
2959 + struct squashfs_dir_entry sdire;
\r
2960 + if (!squashfs_get_cached_block(i->i_sb, (char *)
\r
2961 + &sdire, next_block, next_offset,
\r
2962 + sizeof(sdire), &next_block,
\r
2964 + goto failed_read;
\r
2966 + length += sizeof(sdire);
\r
2967 + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
\r
2969 + if (!squashfs_get_cached_block(i->i_sb, (char *)
\r
2970 + dire, next_block, next_offset,
\r
2971 + sizeof(*dire), &next_block,
\r
2973 + goto failed_read;
\r
2975 + length += sizeof(*dire);
\r
2978 + if (!squashfs_get_cached_block(i->i_sb, dire->name,
\r
2979 + next_block, next_offset,
\r
2980 + dire->size + 1, &next_block,
\r
2982 + goto failed_read;
\r
2984 + length += dire->size + 1;
\r
2986 + if (file->f_pos >= length)
\r
2989 + dire->name[dire->size + 1] = '\0';
\r
2991 + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
\r
2992 + (unsigned int) dirent, dire->name,
\r
2993 + dire->size + 1, (int) file->f_pos,
\r
2994 + dirh.start_block, dire->offset,
\r
2995 + dirh.inode_number + dire->inode_number,
\r
2996 + squashfs_filetype_table[dire->type]);
\r
2998 + if (filldir(dirent, dire->name, dire->size + 1,
\r
3000 + dirh.inode_number + dire->inode_number,
\r
3001 + squashfs_filetype_table[dire->type])
\r
3003 + TRACE("Filldir returned less than 0\n");
\r
3006 + file->f_pos = length;
\r
3015 + ERROR("Unable to read directory block [%llx:%x]\n", next_block,
\r
3022 +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,
\r
3023 + struct nameidata *nd)
\r
3025 + const unsigned char *name = dentry->d_name.name;
\r
3026 + int len = dentry->d_name.len;
\r
3027 + struct inode *inode = NULL;
\r
3028 + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
\r
3029 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
3030 + long long next_block = SQUASHFS_I(i)->start_block +
\r
3031 + sblk->directory_table_start;
\r
3032 + int next_offset = SQUASHFS_I(i)->offset, length = 0,
\r
3034 + struct squashfs_dir_header dirh;
\r
3035 + struct squashfs_dir_entry *dire;
\r
3037 + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
\r
3039 + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
\r
3040 + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
\r
3041 + ERROR("Failed to allocate squashfs_dir_entry\n");
\r
3042 + goto exit_lookup;
\r
3045 + if (len > SQUASHFS_NAME_LEN)
\r
3046 + goto exit_lookup;
\r
3048 + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
\r
3049 + SQUASHFS_I(i)->u.s2.directory_index_start,
\r
3050 + SQUASHFS_I(i)->u.s2.directory_index_offset,
\r
3051 + SQUASHFS_I(i)->u.s2.directory_index_count, name,
\r
3054 + while (length < i_size_read(i)) {
\r
3055 + /* read directory header */
\r
3056 + if (msblk->swap) {
\r
3057 + struct squashfs_dir_header sdirh;
\r
3058 + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
\r
3059 + next_block, next_offset, sizeof(sdirh),
\r
3060 + &next_block, &next_offset))
\r
3061 + goto failed_read;
\r
3063 + length += sizeof(sdirh);
\r
3064 + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
\r
3066 + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
\r
3067 + next_block, next_offset, sizeof(dirh),
\r
3068 + &next_block, &next_offset))
\r
3069 + goto failed_read;
\r
3071 + length += sizeof(dirh);
\r
3074 + dir_count = dirh.count + 1;
\r
3075 + while (dir_count--) {
\r
3076 + if (msblk->swap) {
\r
3077 + struct squashfs_dir_entry sdire;
\r
3078 + if (!squashfs_get_cached_block(i->i_sb, (char *)
\r
3079 + &sdire, next_block,next_offset,
\r
3080 + sizeof(sdire), &next_block,
\r
3082 + goto failed_read;
\r
3084 + length += sizeof(sdire);
\r
3085 + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
\r
3087 + if (!squashfs_get_cached_block(i->i_sb, (char *)
\r
3088 + dire, next_block,next_offset,
\r
3089 + sizeof(*dire), &next_block,
\r
3091 + goto failed_read;
\r
3093 + length += sizeof(*dire);
\r
3096 + if (!squashfs_get_cached_block(i->i_sb, dire->name,
\r
3097 + next_block, next_offset, dire->size + 1,
\r
3098 + &next_block, &next_offset))
\r
3099 + goto failed_read;
\r
3101 + length += dire->size + 1;
\r
3103 + if (name[0] < dire->name[0])
\r
3104 + goto exit_lookup;
\r
3106 + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) {
\r
3107 + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block,
\r
3110 + TRACE("calling squashfs_iget for directory "
\r
3111 + "entry %s, inode %x:%x, %d\n", name,
\r
3112 + dirh.start_block, dire->offset,
\r
3113 + dirh.inode_number + dire->inode_number);
\r
3115 + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number);
\r
3117 + goto exit_lookup;
\r
3125 + return d_splice_alias(inode, dentry);
\r
3126 + d_add(dentry, inode);
\r
3127 + return ERR_PTR(0);
\r
3130 + ERROR("Unable to read directory block [%llx:%x]\n", next_block,
\r
3132 + goto exit_lookup;
\r
3136 +static int squashfs_remount(struct super_block *s, int *flags, char *data)
\r
3138 + *flags |= MS_RDONLY;
\r
3143 +static void squashfs_put_super(struct super_block *s)
\r
3147 + if (s->s_fs_info) {
\r
3148 + struct squashfs_sb_info *sbi = s->s_fs_info;
\r
3149 + if (sbi->block_cache)
\r
3150 + for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
\r
3151 + if (sbi->block_cache[i].block !=
\r
3152 + SQUASHFS_INVALID_BLK)
\r
3153 + kfree(sbi->block_cache[i].data);
\r
3154 + if (sbi->fragment)
\r
3155 + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++)
\r
3156 + SQUASHFS_FREE(sbi->fragment[i].data);
\r
3157 + kfree(sbi->fragment);
\r
3158 + kfree(sbi->block_cache);
\r
3159 + kfree(sbi->read_page);
\r
3160 + kfree(sbi->uid);
\r
3161 + kfree(sbi->fragment_index);
\r
3162 + kfree(sbi->fragment_index_2);
\r
3163 + kfree(sbi->meta_index);
\r
3164 + kfree(s->s_fs_info);
\r
3165 + s->s_fs_info = NULL;
\r
3170 +static int squashfs_get_sb(struct file_system_type *fs_type, int flags,
\r
3171 + const char *dev_name, void *data,
\r
3172 + struct vfsmount *mnt)
\r
3174 + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,
\r
3179 +static void free_sqlzma(void)
\r
3182 + struct sqlzma *p;
\r
3184 + for_each_online_cpu(cpu) {
\r
3185 + p = per_cpu(sqlzma, cpu);
\r
3187 +#ifdef KeepPreemptive
\r
3188 + mutex_destroy(&p->mtx);
\r
3190 + sqlzma_fin(&p->un);
\r
3196 +static int __init init_squashfs_fs(void)
\r
3198 + struct sqlzma *p;
\r
3200 + int err = init_inodecache();
\r
3204 + for_each_online_cpu(cpu) {
\r
3205 + dpri("%d: %p\n", cpu, per_cpu(sqlzma, cpu));
\r
3207 + p = kmalloc(sizeof(struct sqlzma), GFP_KERNEL);
\r
3209 +#ifdef KeepPreemptive
\r
3210 + mutex_init(&p->mtx);
\r
3212 + err = sqlzma_init(&p->un, 1, 0);
\r
3213 + if (unlikely(err)) {
\r
3214 + ERROR("Failed to intialize uncompress workspace\n");
\r
3217 + per_cpu(sqlzma, cpu) = p;
\r
3222 + if (unlikely(err)) {
\r
3227 + printk(KERN_INFO "squashfs: version 3.2-r2 (2007/01/15) "
\r
3228 + "Phillip Lougher\n"
\r
3229 + "squashfs: LZMA suppport for slax.org by jro\n");
\r
3231 + if ((err = register_filesystem(&squashfs_fs_type))) {
\r
3233 + destroy_inodecache();
\r
3241 +static void __exit exit_squashfs_fs(void)
\r
3243 + unregister_filesystem(&squashfs_fs_type);
\r
3245 + destroy_inodecache();
\r
3249 +static struct kmem_cache * squashfs_inode_cachep;
\r
3252 +static struct inode *squashfs_alloc_inode(struct super_block *sb)
\r
3254 + struct squashfs_inode_info *ei;
\r
3255 + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
\r
3258 + return &ei->vfs_inode;
\r
3262 +static void squashfs_destroy_inode(struct inode *inode)
\r
3264 + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
\r
3268 +static void init_once(struct kmem_cache * cachep, void * foo)
\r
3270 + struct squashfs_inode_info *ei = foo;
\r
3271 + inode_init_once(&ei->vfs_inode);
\r
3275 +static int __init init_inodecache(void)
\r
3277 + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
\r
3278 + sizeof(struct squashfs_inode_info),
\r
3279 + 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
\r
3281 + if (squashfs_inode_cachep == NULL)
\r
3287 +static void destroy_inodecache(void)
\r
3289 + kmem_cache_destroy(squashfs_inode_cachep);
\r
3293 +module_init(init_squashfs_fs);
\r
3294 +module_exit(exit_squashfs_fs);
\r
3295 +MODULE_DESCRIPTION("squashfs 3.2-r2, a compressed read-only filesystem, and LZMA suppport for slax.org");
\r
3296 +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>, and LZMA suppport for slax.org by jro");
\r
3297 +MODULE_LICENSE("GPL");
\r
3298 diff -urN linux-2.6.23/fs/squashfs/module.c linux-2.6.23.sqlzma/fs/squashfs/module.c
\r
3299 --- linux-2.6.23/fs/squashfs/module.c 1969-12-31 19:00:00.000000000 -0500
\r
3300 +++ linux-2.6.23.sqlzma/fs/squashfs/module.c 2007-10-14 12:58:25.000000000 -0400
\r
3304 + * Copyright (C) 2006 Junjiro Okajima
\r
3305 + * Copyright (C) 2006 Tomas Matejicek, slax.org
\r
3307 + * LICENSE follows the described one in lzma.txt.
\r
3310 +/* $Id: module.c,v 1.5 2006/11/27 03:54:58 jro Exp $ */
\r
3312 +#include <linux/init.h>
\r
3313 +#include <linux/module.h>
\r
3315 +#include "LzmaDecode.c"
\r
3317 +EXPORT_SYMBOL(LzmaDecodeProperties);
\r
3318 +EXPORT_SYMBOL(LzmaDecode);
\r
3321 +static int __init unlzma_init(void)
\r
3326 +static void __exit unlzma_exit(void)
\r
3330 +module_init(unlzma_init);
\r
3331 +module_exit(unlzma_exit);
\r
3334 +MODULE_LICENSE("GPL");
\r
3335 +MODULE_VERSION("$Id: module.c,v 1.5 2006/11/27 03:54:58 jro Exp $");
\r
3336 +MODULE_DESCRIPTION("LZMA uncompress. "
\r
3337 + "A tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org.");
\r
3338 diff -urN linux-2.6.23/fs/squashfs/sqlzma.h linux-2.6.23.sqlzma/fs/squashfs/sqlzma.h
\r
3339 --- linux-2.6.23/fs/squashfs/sqlzma.h 1969-12-31 19:00:00.000000000 -0500
\r
3340 +++ linux-2.6.23.sqlzma/fs/squashfs/sqlzma.h 2007-10-14 13:07:12.000000000 -0400
\r
3343 + * Copyright (C) 2006 Junjiro Okajima
\r
3344 + * Copyright (C) 2006 Tomas Matejicek, slax.org
\r
3346 + * LICENSE follows the described one in lzma.
\r
3349 +/* $Id: sqlzma.h,v 1.13 2007/01/07 15:12:48 jro Exp $ */
\r
3351 +#ifndef __sqlzma_h__
\r
3352 +#define __sqlzma_h__
\r
3354 +#ifndef __KERNEL__
\r
3355 +#include <stdlib.h>
\r
3356 +#include <string.h>
\r
3357 +#include <zlib.h>
\r
3358 +#ifdef _REENTRANT
\r
3359 +#include <pthread.h>
\r
3362 +#include <linux/zlib.h>
\r
3364 +#define _7ZIP_BYTE_DEFINED
\r
3367 + * detect the compression method automatically by the first byte of compressed
\r
3369 + * according to rfc1950, the first byte of zlib compression must be 0x?8.
\r
3371 +#define is_lzma(c) (c == 0x5d)
\r
3373 +/* ---------------------------------------------------------------------- */
\r
3375 +#ifdef __cplusplus
\r
3379 +#ifndef __KERNEL__
\r
3380 +/* for mksquashfs only */
\r
3381 +int sqlzma_cm(int lzma, z_stream *stream, Bytef *next_in, uInt avail_in,
\r
3382 + Bytef *next_out, uInt avail_out);
\r
3385 +/* ---------------------------------------------------------------------- */
\r
3387 + * Three patterns for sqlzma uncompression. very dirty code.
\r
3388 + * - kernel space (squashfs kernel module)
\r
3389 + * - user space with pthread (mksquashfs)
\r
3390 + * - user space without pthread (unsquashfs)
\r
3393 +struct sized_buf {
\r
3394 + unsigned int sz;
\r
3395 + unsigned char *buf;
\r
3398 +enum {SQUN_PROB, SQUN_RESULT, SQUN_LAST};
\r
3399 +struct sqlzma_un {
\r
3401 + struct sized_buf un_a[SQUN_LAST];
\r
3402 + unsigned char un_prob[31960]; /* unlzma 64KB */
\r
3403 + z_stream un_stream;
\r
3404 +#define un_cmbuf un_stream.next_in
\r
3405 +#define un_cmlen un_stream.avail_in
\r
3406 +#define un_resbuf un_stream.next_out
\r
3407 +#define un_resroom un_stream.avail_out
\r
3408 +#define un_reslen un_stream.total_out
\r
3411 +int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz);
\r
3412 +int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst);
\r
3413 +void sqlzma_fin(struct sqlzma_un *un);
\r
3415 +/* ---------------------------------------------------------------------- */
\r
3417 +#ifdef __cplusplus
\r
3421 diff -urN linux-2.6.23/fs/squashfs/sqmagic.h linux-2.6.23.sqlzma/fs/squashfs/sqmagic.h
\r
3422 --- linux-2.6.23/fs/squashfs/sqmagic.h 1969-12-31 19:00:00.000000000 -0500
\r
3423 +++ linux-2.6.23.sqlzma/fs/squashfs/sqmagic.h 2007-10-14 14:32:24.000000000 -0400
\r
3426 + * Copyright (C) 2006 Junjiro Okajima
\r
3427 + * Copyright (C) 2006 Tomas Matejicek, slax.org
\r
3429 + * LICENSE must follow the one in squashfs.
\r
3432 +/* $Id: sqmagic.h,v 1.2 2006/11/27 03:54:58 jro Exp $ */
\r
3434 +#ifndef __sqmagic_h__
\r
3435 +#define __sqmagic_h__
\r
3437 +/* see SQUASHFS_MAGIC in squashfs_fs.h */
\r
3438 +#define SQUASHFS_MAGIC_LZMA 0x71736873
\r
3439 +#define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371
\r
3442 diff -urN linux-2.6.23/fs/squashfs/squashfs.h linux-2.6.23.sqlzma/fs/squashfs/squashfs.h
\r
3443 --- linux-2.6.23/fs/squashfs/squashfs.h 1969-12-31 19:00:00.000000000 -0500
\r
3444 +++ linux-2.6.23.sqlzma/fs/squashfs/squashfs.h 2007-10-14 10:24:31.000000000 -0400
\r
3447 + * Squashfs - a compressed read only filesystem for Linux
\r
3449 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
\r
3450 + * Phillip Lougher <phillip@lougher.org.uk>
\r
3452 + * This program is free software; you can redistribute it and/or
\r
3453 + * modify it under the terms of the GNU General Public License
\r
3454 + * as published by the Free Software Foundation; either version 2,
\r
3455 + * or (at your option) any later version.
\r
3457 + * This program is distributed in the hope that it will be useful,
\r
3458 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
3459 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
3460 + * GNU General Public License for more details.
\r
3462 + * You should have received a copy of the GNU General Public License
\r
3463 + * along with this program; if not, write to the Free Software
\r
3464 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
3469 +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
\r
3470 +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
\r
3473 +#ifdef SQUASHFS_TRACE
\r
3474 +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
\r
3476 +#define TRACE(s, args...) {}
\r
3479 +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args)
\r
3481 +#define SERROR(s, args...) do { \
\r
3483 + printk(KERN_ERR "SQUASHFS error: "s, ## args);\
\r
3486 +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args)
\r
3488 +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
\r
3490 + return list_entry(inode, struct squashfs_inode_info, vfs_inode);
\r
3493 +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)
\r
3494 +#define SQSH_EXTERN
\r
3495 +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
\r
3496 + long long index, unsigned int length,
\r
3497 + long long *next_index, int srclength);
\r
3498 +extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
\r
3499 + long long block, unsigned int offset,
\r
3500 + int length, long long *next_block,
\r
3501 + unsigned int *next_offset);
\r
3502 +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct
\r
3503 + squashfs_fragment_cache *fragment);
\r
3504 +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block
\r
3505 + *s, long long start_block,
\r
3507 +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number);
\r
3508 +extern const struct address_space_operations squashfs_symlink_aops;
\r
3509 +extern const struct address_space_operations squashfs_aops;
\r
3510 +extern const struct address_space_operations squashfs_aops_4K;
\r
3511 +extern struct inode_operations squashfs_dir_inode_ops;
\r
3513 +#define SQSH_EXTERN static
\r
3516 +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
\r
3517 +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
\r
3519 +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
\r
3525 +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
\r
3526 +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
\r
3528 +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
\r
3533 diff -urN linux-2.6.23/fs/squashfs/squashfs2_0.c linux-2.6.23.sqlzma/fs/squashfs/squashfs2_0.c
\r
3534 --- linux-2.6.23/fs/squashfs/squashfs2_0.c 1969-12-31 19:00:00.000000000 -0500
\r
3535 +++ linux-2.6.23.sqlzma/fs/squashfs/squashfs2_0.c 2007-10-14 10:24:31.000000000 -0400
\r
3538 + * Squashfs - a compressed read only filesystem for Linux
\r
3540 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
\r
3541 + * Phillip Lougher <phillip@lougher.org.uk>
\r
3543 + * This program is free software; you can redistribute it and/or
\r
3544 + * modify it under the terms of the GNU General Public License
\r
3545 + * as published by the Free Software Foundation; either version 2,
\r
3546 + * or (at your option) any later version.
\r
3548 + * This program is distributed in the hope that it will be useful,
\r
3549 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
3550 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
3551 + * GNU General Public License for more details.
\r
3553 + * You should have received a copy of the GNU General Public License
\r
3554 + * along with this program; if not, write to the Free Software
\r
3555 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
3560 +#include <linux/squashfs_fs.h>
\r
3561 +#include <linux/module.h>
\r
3562 +#include <linux/zlib.h>
\r
3563 +#include <linux/fs.h>
\r
3564 +#include <linux/squashfs_fs_sb.h>
\r
3565 +#include <linux/squashfs_fs_i.h>
\r
3567 +#include "squashfs.h"
\r
3568 +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
\r
3569 +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,
\r
3570 + struct nameidata *);
\r
3572 +static struct file_operations squashfs_dir_ops_2 = {
\r
3573 + .read = generic_read_dir,
\r
3574 + .readdir = squashfs_readdir_2
\r
3577 +static struct inode_operations squashfs_dir_inode_ops_2 = {
\r
3578 + .lookup = squashfs_lookup_2
\r
3581 +static unsigned char squashfs_filetype_table[] = {
\r
3582 + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
\r
3585 +static int read_fragment_index_table_2(struct super_block *s)
\r
3587 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
3588 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
3590 + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
\r
3591 + (sblk->fragments), GFP_KERNEL))) {
\r
3592 + ERROR("Failed to allocate uid/gid table\n");
\r
3596 + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
\r
3597 + !squashfs_read_data(s, (char *)
\r
3598 + msblk->fragment_index_2,
\r
3599 + sblk->fragment_table_start,
\r
3600 + SQUASHFS_FRAGMENT_INDEX_BYTES_2
\r
3601 + (sblk->fragments) |
\r
3602 + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {
\r
3603 + ERROR("unable to read fragment index table\n");
\r
3607 + if (msblk->swap) {
\r
3609 + unsigned int fragment;
\r
3611 + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
\r
3613 + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
\r
3614 + &msblk->fragment_index_2[i], 1);
\r
3615 + msblk->fragment_index_2[i] = fragment;
\r
3623 +static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
\r
3624 + long long *fragment_start_block,
\r
3625 + unsigned int *fragment_size)
\r
3627 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
3628 + long long start_block =
\r
3629 + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
\r
3630 + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
\r
3631 + struct squashfs_fragment_entry_2 fragment_entry;
\r
3633 + if (msblk->swap) {
\r
3634 + struct squashfs_fragment_entry_2 sfragment_entry;
\r
3636 + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
\r
3637 + start_block, offset,
\r
3638 + sizeof(sfragment_entry), &start_block,
\r
3641 + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
\r
3643 + if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
\r
3644 + start_block, offset,
\r
3645 + sizeof(fragment_entry), &start_block,
\r
3649 + *fragment_start_block = fragment_entry.start_block;
\r
3650 + *fragment_size = fragment_entry.size;
\r
3659 +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
\r
3660 + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
\r
3662 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
3665 + i->i_mtime.tv_sec = sblk->mkfs_time;
\r
3666 + i->i_atime.tv_sec = sblk->mkfs_time;
\r
3667 + i->i_ctime.tv_sec = sblk->mkfs_time;
\r
3668 + i->i_uid = msblk->uid[inodeb->uid];
\r
3669 + i->i_mode = inodeb->mode;
\r
3672 + if (inodeb->guid == SQUASHFS_GUIDS)
\r
3673 + i->i_gid = i->i_uid;
\r
3675 + i->i_gid = msblk->guid[inodeb->guid];
\r
3679 +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode)
\r
3681 + struct super_block *s = i->i_sb;
\r
3682 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
3683 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
3684 + unsigned int block = SQUASHFS_INODE_BLK(inode) +
\r
3685 + sblk->inode_table_start;
\r
3686 + unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
\r
3687 + unsigned int ino = i->i_ino;
\r
3688 + long long next_block;
\r
3689 + unsigned int next_offset;
\r
3690 + union squashfs_inode_header_2 id, sid;
\r
3691 + struct squashfs_base_inode_header_2 *inodeb = &id.base,
\r
3692 + *sinodeb = &sid.base;
\r
3694 + TRACE("Entered squashfs_iget\n");
\r
3696 + if (msblk->swap) {
\r
3697 + if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
\r
3698 + offset, sizeof(*sinodeb), &next_block,
\r
3700 + goto failed_read;
\r
3701 + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
\r
3702 + sizeof(*sinodeb));
\r
3704 + if (!squashfs_get_cached_block(s, (char *) inodeb, block,
\r
3705 + offset, sizeof(*inodeb), &next_block,
\r
3707 + goto failed_read;
\r
3709 + squashfs_new_inode(msblk, i, inodeb, ino);
\r
3711 + switch(inodeb->inode_type) {
\r
3712 + case SQUASHFS_FILE_TYPE: {
\r
3713 + struct squashfs_reg_inode_header_2 *inodep = &id.reg;
\r
3714 + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
\r
3715 + long long frag_blk;
\r
3716 + unsigned int frag_size = 0;
\r
3718 + if (msblk->swap) {
\r
3719 + if (!squashfs_get_cached_block(s, (char *)
\r
3720 + sinodep, block, offset,
\r
3721 + sizeof(*sinodep), &next_block,
\r
3723 + goto failed_read;
\r
3724 + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
\r
3726 + if (!squashfs_get_cached_block(s, (char *)
\r
3727 + inodep, block, offset,
\r
3728 + sizeof(*inodep), &next_block,
\r
3730 + goto failed_read;
\r
3732 + frag_blk = SQUASHFS_INVALID_BLK;
\r
3733 + if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
\r
3734 + !get_fragment_location_2(s,
\r
3735 + inodep->fragment, &frag_blk, &frag_size))
\r
3736 + goto failed_read;
\r
3738 + i->i_size = inodep->file_size;
\r
3739 + i->i_fop = &generic_ro_fops;
\r
3740 + i->i_mode |= S_IFREG;
\r
3741 + i->i_mtime.tv_sec = inodep->mtime;
\r
3742 + i->i_atime.tv_sec = inodep->mtime;
\r
3743 + i->i_ctime.tv_sec = inodep->mtime;
\r
3744 + i->i_blocks = ((i->i_size - 1) >> 9) + 1;
\r
3745 + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
\r
3746 + SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
\r
3747 + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
\r
3748 + SQUASHFS_I(i)->start_block = inodep->start_block;
\r
3749 + SQUASHFS_I(i)->u.s1.block_list_start = next_block;
\r
3750 + SQUASHFS_I(i)->offset = next_offset;
\r
3751 + if (sblk->block_size > 4096)
\r
3752 + i->i_data.a_ops = &squashfs_aops;
\r
3754 + i->i_data.a_ops = &squashfs_aops_4K;
\r
3756 + TRACE("File inode %x:%x, start_block %x, "
\r
3757 + "block_list_start %llx, offset %x\n",
\r
3758 + SQUASHFS_INODE_BLK(inode), offset,
\r
3759 + inodep->start_block, next_block,
\r
3763 + case SQUASHFS_DIR_TYPE: {
\r
3764 + struct squashfs_dir_inode_header_2 *inodep = &id.dir;
\r
3765 + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
\r
3767 + if (msblk->swap) {
\r
3768 + if (!squashfs_get_cached_block(s, (char *)
\r
3769 + sinodep, block, offset,
\r
3770 + sizeof(*sinodep), &next_block,
\r
3772 + goto failed_read;
\r
3773 + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
\r
3775 + if (!squashfs_get_cached_block(s, (char *)
\r
3776 + inodep, block, offset,
\r
3777 + sizeof(*inodep), &next_block,
\r
3779 + goto failed_read;
\r
3781 + i->i_size = inodep->file_size;
\r
3782 + i->i_op = &squashfs_dir_inode_ops_2;
\r
3783 + i->i_fop = &squashfs_dir_ops_2;
\r
3784 + i->i_mode |= S_IFDIR;
\r
3785 + i->i_mtime.tv_sec = inodep->mtime;
\r
3786 + i->i_atime.tv_sec = inodep->mtime;
\r
3787 + i->i_ctime.tv_sec = inodep->mtime;
\r
3788 + SQUASHFS_I(i)->start_block = inodep->start_block;
\r
3789 + SQUASHFS_I(i)->offset = inodep->offset;
\r
3790 + SQUASHFS_I(i)->u.s2.directory_index_count = 0;
\r
3791 + SQUASHFS_I(i)->u.s2.parent_inode = 0;
\r
3793 + TRACE("Directory inode %x:%x, start_block %x, offset "
\r
3794 + "%x\n", SQUASHFS_INODE_BLK(inode),
\r
3795 + offset, inodep->start_block,
\r
3796 + inodep->offset);
\r
3799 + case SQUASHFS_LDIR_TYPE: {
\r
3800 + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
\r
3801 + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
\r
3803 + if (msblk->swap) {
\r
3804 + if (!squashfs_get_cached_block(s, (char *)
\r
3805 + sinodep, block, offset,
\r
3806 + sizeof(*sinodep), &next_block,
\r
3808 + goto failed_read;
\r
3809 + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
\r
3812 + if (!squashfs_get_cached_block(s, (char *)
\r
3813 + inodep, block, offset,
\r
3814 + sizeof(*inodep), &next_block,
\r
3816 + goto failed_read;
\r
3818 + i->i_size = inodep->file_size;
\r
3819 + i->i_op = &squashfs_dir_inode_ops_2;
\r
3820 + i->i_fop = &squashfs_dir_ops_2;
\r
3821 + i->i_mode |= S_IFDIR;
\r
3822 + i->i_mtime.tv_sec = inodep->mtime;
\r
3823 + i->i_atime.tv_sec = inodep->mtime;
\r
3824 + i->i_ctime.tv_sec = inodep->mtime;
\r
3825 + SQUASHFS_I(i)->start_block = inodep->start_block;
\r
3826 + SQUASHFS_I(i)->offset = inodep->offset;
\r
3827 + SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
\r
3828 + SQUASHFS_I(i)->u.s2.directory_index_offset =
\r
3830 + SQUASHFS_I(i)->u.s2.directory_index_count =
\r
3831 + inodep->i_count;
\r
3832 + SQUASHFS_I(i)->u.s2.parent_inode = 0;
\r
3834 + TRACE("Long directory inode %x:%x, start_block %x, "
\r
3836 + SQUASHFS_INODE_BLK(inode), offset,
\r
3837 + inodep->start_block, inodep->offset);
\r
3840 + case SQUASHFS_SYMLINK_TYPE: {
\r
3841 + struct squashfs_symlink_inode_header_2 *inodep =
\r
3843 + struct squashfs_symlink_inode_header_2 *sinodep =
\r
3846 + if (msblk->swap) {
\r
3847 + if (!squashfs_get_cached_block(s, (char *)
\r
3848 + sinodep, block, offset,
\r
3849 + sizeof(*sinodep), &next_block,
\r
3851 + goto failed_read;
\r
3852 + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
\r
3855 + if (!squashfs_get_cached_block(s, (char *)
\r
3856 + inodep, block, offset,
\r
3857 + sizeof(*inodep), &next_block,
\r
3859 + goto failed_read;
\r
3861 + i->i_size = inodep->symlink_size;
\r
3862 + i->i_op = &page_symlink_inode_operations;
\r
3863 + i->i_data.a_ops = &squashfs_symlink_aops;
\r
3864 + i->i_mode |= S_IFLNK;
\r
3865 + SQUASHFS_I(i)->start_block = next_block;
\r
3866 + SQUASHFS_I(i)->offset = next_offset;
\r
3868 + TRACE("Symbolic link inode %x:%x, start_block %llx, "
\r
3870 + SQUASHFS_INODE_BLK(inode), offset,
\r
3871 + next_block, next_offset);
\r
3874 + case SQUASHFS_BLKDEV_TYPE:
\r
3875 + case SQUASHFS_CHRDEV_TYPE: {
\r
3876 + struct squashfs_dev_inode_header_2 *inodep = &id.dev;
\r
3877 + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
\r
3879 + if (msblk->swap) {
\r
3880 + if (!squashfs_get_cached_block(s, (char *)
\r
3881 + sinodep, block, offset,
\r
3882 + sizeof(*sinodep), &next_block,
\r
3884 + goto failed_read;
\r
3885 + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
\r
3887 + if (!squashfs_get_cached_block(s, (char *)
\r
3888 + inodep, block, offset,
\r
3889 + sizeof(*inodep), &next_block,
\r
3891 + goto failed_read;
\r
3893 + i->i_mode |= (inodeb->inode_type ==
\r
3894 + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
\r
3896 + init_special_inode(i, i->i_mode,
\r
3897 + old_decode_dev(inodep->rdev));
\r
3899 + TRACE("Device inode %x:%x, rdev %x\n",
\r
3900 + SQUASHFS_INODE_BLK(inode), offset,
\r
3904 + case SQUASHFS_FIFO_TYPE:
\r
3905 + case SQUASHFS_SOCKET_TYPE: {
\r
3907 + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
\r
3908 + ? S_IFIFO : S_IFSOCK;
\r
3909 + init_special_inode(i, i->i_mode, 0);
\r
3913 + ERROR("Unknown inode type %d in squashfs_iget!\n",
\r
3914 + inodeb->inode_type);
\r
3915 + goto failed_read1;
\r
3921 + ERROR("Unable to read inode [%x:%x]\n", block, offset);
\r
3928 +static int get_dir_index_using_offset(struct super_block *s, long long
\r
3929 + *next_block, unsigned int *next_offset,
\r
3930 + long long index_start,
\r
3931 + unsigned int index_offset, int i_count,
\r
3932 + long long f_pos)
\r
3934 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
3935 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
3936 + int i, length = 0;
\r
3937 + struct squashfs_dir_index_2 index;
\r
3939 + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
\r
3940 + i_count, (unsigned int) f_pos);
\r
3945 + for (i = 0; i < i_count; i++) {
\r
3946 + if (msblk->swap) {
\r
3947 + struct squashfs_dir_index_2 sindex;
\r
3948 + squashfs_get_cached_block(s, (char *) &sindex,
\r
3949 + index_start, index_offset,
\r
3950 + sizeof(sindex), &index_start,
\r
3952 + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
\r
3954 + squashfs_get_cached_block(s, (char *) &index,
\r
3955 + index_start, index_offset,
\r
3956 + sizeof(index), &index_start,
\r
3959 + if (index.index > f_pos)
\r
3962 + squashfs_get_cached_block(s, NULL, index_start, index_offset,
\r
3963 + index.size + 1, &index_start,
\r
3966 + length = index.index;
\r
3967 + *next_block = index.start_block + sblk->directory_table_start;
\r
3970 + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
\r
3977 +static int get_dir_index_using_name(struct super_block *s, long long
\r
3978 + *next_block, unsigned int *next_offset,
\r
3979 + long long index_start,
\r
3980 + unsigned int index_offset, int i_count,
\r
3981 + const char *name, int size)
\r
3983 + struct squashfs_sb_info *msblk = s->s_fs_info;
\r
3984 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
3985 + int i, length = 0;
\r
3986 + struct squashfs_dir_index_2 *index;
\r
3989 + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
\r
3991 + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
\r
3992 + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
\r
3993 + ERROR("Failed to allocate squashfs_dir_index\n");
\r
3997 + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1);
\r
3998 + strncpy(str, name, size);
\r
3999 + str[size] = '\0';
\r
4001 + for (i = 0; i < i_count; i++) {
\r
4002 + if (msblk->swap) {
\r
4003 + struct squashfs_dir_index_2 sindex;
\r
4004 + squashfs_get_cached_block(s, (char *) &sindex,
\r
4005 + index_start, index_offset,
\r
4006 + sizeof(sindex), &index_start,
\r
4008 + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
\r
4010 + squashfs_get_cached_block(s, (char *) index,
\r
4011 + index_start, index_offset,
\r
4012 + sizeof(struct squashfs_dir_index_2),
\r
4013 + &index_start, &index_offset);
\r
4015 + squashfs_get_cached_block(s, index->name, index_start,
\r
4016 + index_offset, index->size + 1,
\r
4017 + &index_start, &index_offset);
\r
4019 + index->name[index->size + 1] = '\0';
\r
4021 + if (strcmp(index->name, str) > 0)
\r
4024 + length = index->index;
\r
4025 + *next_block = index->start_block + sblk->directory_table_start;
\r
4028 + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
\r
4035 +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
\r
4037 + struct inode *i = file->f_dentry->d_inode;
\r
4038 + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
\r
4039 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
4040 + long long next_block = SQUASHFS_I(i)->start_block +
\r
4041 + sblk->directory_table_start;
\r
4042 + int next_offset = SQUASHFS_I(i)->offset, length = 0,
\r
4044 + struct squashfs_dir_header_2 dirh;
\r
4045 + struct squashfs_dir_entry_2 *dire;
\r
4047 + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
\r
4049 + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
\r
4050 + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
\r
4051 + ERROR("Failed to allocate squashfs_dir_entry\n");
\r
4055 + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
\r
4056 + SQUASHFS_I(i)->u.s2.directory_index_start,
\r
4057 + SQUASHFS_I(i)->u.s2.directory_index_offset,
\r
4058 + SQUASHFS_I(i)->u.s2.directory_index_count,
\r
4061 + while (length < i_size_read(i)) {
\r
4062 + /* read directory header */
\r
4063 + if (msblk->swap) {
\r
4064 + struct squashfs_dir_header_2 sdirh;
\r
4066 + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
\r
4067 + next_block, next_offset, sizeof(sdirh),
\r
4068 + &next_block, &next_offset))
\r
4069 + goto failed_read;
\r
4071 + length += sizeof(sdirh);
\r
4072 + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
\r
4074 + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
\r
4075 + next_block, next_offset, sizeof(dirh),
\r
4076 + &next_block, &next_offset))
\r
4077 + goto failed_read;
\r
4079 + length += sizeof(dirh);
\r
4082 + dir_count = dirh.count + 1;
\r
4083 + while (dir_count--) {
\r
4084 + if (msblk->swap) {
\r
4085 + struct squashfs_dir_entry_2 sdire;
\r
4086 + if (!squashfs_get_cached_block(i->i_sb, (char *)
\r
4087 + &sdire, next_block, next_offset,
\r
4088 + sizeof(sdire), &next_block,
\r
4090 + goto failed_read;
\r
4092 + length += sizeof(sdire);
\r
4093 + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
\r
4095 + if (!squashfs_get_cached_block(i->i_sb, (char *)
\r
4096 + dire, next_block, next_offset,
\r
4097 + sizeof(*dire), &next_block,
\r
4099 + goto failed_read;
\r
4101 + length += sizeof(*dire);
\r
4104 + if (!squashfs_get_cached_block(i->i_sb, dire->name,
\r
4105 + next_block, next_offset,
\r
4106 + dire->size + 1, &next_block,
\r
4108 + goto failed_read;
\r
4110 + length += dire->size + 1;
\r
4112 + if (file->f_pos >= length)
\r
4115 + dire->name[dire->size + 1] = '\0';
\r
4117 + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
\r
4118 + (unsigned int) dirent, dire->name,
\r
4119 + dire->size + 1, (int) file->f_pos,
\r
4120 + dirh.start_block, dire->offset,
\r
4121 + squashfs_filetype_table[dire->type]);
\r
4123 + if (filldir(dirent, dire->name, dire->size + 1,
\r
4124 + file->f_pos, SQUASHFS_MK_VFS_INODE(
\r
4125 + dirh.start_block, dire->offset),
\r
4126 + squashfs_filetype_table[dire->type])
\r
4128 + TRACE("Filldir returned less than 0\n");
\r
4131 + file->f_pos = length;
\r
4140 + ERROR("Unable to read directory block [%llx:%x]\n", next_block,
\r
4147 +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
\r
4148 + struct nameidata *nd)
\r
4150 + const unsigned char *name = dentry->d_name.name;
\r
4151 + int len = dentry->d_name.len;
\r
4152 + struct inode *inode = NULL;
\r
4153 + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
\r
4154 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
4155 + long long next_block = SQUASHFS_I(i)->start_block +
\r
4156 + sblk->directory_table_start;
\r
4157 + int next_offset = SQUASHFS_I(i)->offset, length = 0,
\r
4159 + struct squashfs_dir_header_2 dirh;
\r
4160 + struct squashfs_dir_entry_2 *dire;
\r
4161 + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
\r
4163 + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset);
\r
4165 + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
\r
4166 + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
\r
4167 + ERROR("Failed to allocate squashfs_dir_entry\n");
\r
4171 + if (len > SQUASHFS_NAME_LEN)
\r
4174 + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
\r
4175 + SQUASHFS_I(i)->u.s2.directory_index_start,
\r
4176 + SQUASHFS_I(i)->u.s2.directory_index_offset,
\r
4177 + SQUASHFS_I(i)->u.s2.directory_index_count, name,
\r
4180 + while (length < i_size_read(i)) {
\r
4181 + /* read directory header */
\r
4182 + if (msblk->swap) {
\r
4183 + struct squashfs_dir_header_2 sdirh;
\r
4184 + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
\r
4185 + next_block, next_offset, sizeof(sdirh),
\r
4186 + &next_block, &next_offset))
\r
4187 + goto failed_read;
\r
4189 + length += sizeof(sdirh);
\r
4190 + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
\r
4192 + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
\r
4193 + next_block, next_offset, sizeof(dirh),
\r
4194 + &next_block, &next_offset))
\r
4195 + goto failed_read;
\r
4197 + length += sizeof(dirh);
\r
4200 + dir_count = dirh.count + 1;
\r
4201 + while (dir_count--) {
\r
4202 + if (msblk->swap) {
\r
4203 + struct squashfs_dir_entry_2 sdire;
\r
4204 + if (!squashfs_get_cached_block(i->i_sb, (char *)
\r
4205 + &sdire, next_block,next_offset,
\r
4206 + sizeof(sdire), &next_block,
\r
4208 + goto failed_read;
\r
4210 + length += sizeof(sdire);
\r
4211 + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
\r
4213 + if (!squashfs_get_cached_block(i->i_sb, (char *)
\r
4214 + dire, next_block,next_offset,
\r
4215 + sizeof(*dire), &next_block,
\r
4217 + goto failed_read;
\r
4219 + length += sizeof(*dire);
\r
4222 + if (!squashfs_get_cached_block(i->i_sb, dire->name,
\r
4223 + next_block, next_offset, dire->size + 1,
\r
4224 + &next_block, &next_offset))
\r
4225 + goto failed_read;
\r
4227 + length += dire->size + 1;
\r
4229 + if (sorted && name[0] < dire->name[0])
\r
4232 + if ((len == dire->size + 1) && !strncmp(name,
\r
4233 + dire->name, len)) {
\r
4234 + squashfs_inode_t ino =
\r
4235 + SQUASHFS_MKINODE(dirh.start_block,
\r
4237 + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block,
\r
4240 + TRACE("calling squashfs_iget for directory "
\r
4241 + "entry %s, inode %x:%x, %lld\n", name,
\r
4242 + dirh.start_block, dire->offset, ino);
\r
4244 + inode = squashfs_iget(i->i_sb, ino, inode_number);
\r
4253 + d_add(dentry, inode);
\r
4254 + return ERR_PTR(0);
\r
4257 + ERROR("Unable to read directory block [%llx:%x]\n", next_block,
\r
4263 +int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
\r
4265 + struct squashfs_super_block *sblk = &msblk->sblk;
\r
4267 + msblk->read_inode = squashfs_read_inode_2;
\r
4268 + msblk->read_fragment_index_table = read_fragment_index_table_2;
\r
4270 + sblk->bytes_used = sblk->bytes_used_2;
\r
4271 + sblk->uid_start = sblk->uid_start_2;
\r
4272 + sblk->guid_start = sblk->guid_start_2;
\r
4273 + sblk->inode_table_start = sblk->inode_table_start_2;
\r
4274 + sblk->directory_table_start = sblk->directory_table_start_2;
\r
4275 + sblk->fragment_table_start = sblk->fragment_table_start_2;
\r
4279 diff -urN linux-2.6.23/fs/squashfs/uncomp.c linux-2.6.23.sqlzma/fs/squashfs/uncomp.c
\r
4280 --- linux-2.6.23/fs/squashfs/uncomp.c 1969-12-31 19:00:00.000000000 -0500
\r
4281 +++ linux-2.6.23.sqlzma/fs/squashfs/uncomp.c 2007-10-14 12:43:55.000000000 -0400
\r
4284 + * Copyright (C) 2006, 2007 Junjiro Okajima
\r
4285 + * Copyright (C) 2006, 2007 Tomas Matejicek, slax.org
\r
4287 + * LICENSE follows the described one in lzma.txt.
\r
4290 +/* $Id: uncomp.c,v 1.30 2007/03/04 12:45:53 jro Exp $ */
\r
4292 +/* extract some parts from lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c */
\r
4294 +#ifndef __KERNEL__
\r
4295 +#include <stdio.h>
\r
4296 +#include <stdlib.h>
\r
4297 +#include <string.h>
\r
4298 +#include <errno.h>
\r
4299 +#include <assert.h>
\r
4300 +#include <pthread.h>
\r
4301 +#define unlikely(x) __builtin_expect(!!(x), 0)
\r
4302 +#define BUG_ON(x) assert(!(x))
\r
4303 +/* sqlzma buffers are always larger than a page. true? */
\r
4304 +#define kmalloc(sz,gfp) malloc(sz)
\r
4305 +#define kfree(p) free(p)
\r
4306 +#define zlib_inflate(s, f) inflate(s, f)
\r
4307 +#define zlib_inflateInit(s) inflateInit(s)
\r
4308 +#define zlib_inflateReset(s) inflateReset(s)
\r
4309 +#define zlib_inflateEnd(s) inflateEnd(s)
\r
4311 +#include <linux/init.h>
\r
4312 +#include <linux/module.h>
\r
4313 +#include <linux/kernel.h>
\r
4314 +#include <linux/vmalloc.h>
\r
4315 +#ifndef WARN_ON_ONCE
\r
4316 +#define WARN_ON_ONCE(b) WARN_ON(b)
\r
4318 +#endif /* __KERNEL__ */
\r
4320 +#include "sqlzma.h"
\r
4321 +#include "LzmaDecode.h"
\r
4323 +static int LzmaUncompress(struct sqlzma_un *un)
\r
4325 + int err, i, ret;
\r
4326 + SizeT outSize, inProcessed, outProcessed, srclen;
\r
4327 + /* it's about 24-80 bytes structure, if int is 32-bit */
\r
4328 + CLzmaDecoderState state;
\r
4329 + unsigned char *dst, *src, a[8];
\r
4330 + struct sized_buf *sbuf;
\r
4332 + /* Decode LZMA properties and allocate memory */
\r
4334 + src = (unsigned char *)un->un_cmbuf;
\r
4335 + ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE);
\r
4336 + src += LZMA_PROPERTIES_SIZE;
\r
4337 + if (unlikely(ret != LZMA_RESULT_OK))
\r
4339 + i = LzmaGetNumProbs(&state.Properties);
\r
4340 + if (unlikely(i <= 0))
\r
4342 + i *= sizeof(CProb);
\r
4343 + sbuf = un->un_a + SQUN_PROB;
\r
4344 + if (unlikely(sbuf->sz < i)) {
\r
4345 + if (sbuf->buf && sbuf->buf != un->un_prob)
\r
4346 + kfree(sbuf->buf);
\r
4347 +#ifdef __KERNEL__
\r
4348 + printk("%s:%d: %d --> %d\n", __func__, __LINE__, sbuf->sz, i);
\r
4350 + printf("%d --> %d\n", sbuf->sz, i);
\r
4354 + sbuf->buf = kmalloc(i, GFP_ATOMIC);
\r
4355 + if (unlikely(!sbuf->buf))
\r
4359 + state.Probs = (void*)sbuf->buf;
\r
4361 + /* Read uncompressed size */
\r
4362 + memcpy(a, src, sizeof(a));
\r
4363 + src += sizeof(a);
\r
4364 + outSize = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24);
\r
4367 + dst = un->un_resbuf;
\r
4368 + if (unlikely(!dst || outSize > un->un_reslen))
\r
4370 + un->un_reslen = outSize;
\r
4371 + srclen = un->un_cmlen - (src - un->un_cmbuf);
\r
4373 + /* Decompress */
\r
4374 + err = LzmaDecode(&state, src, srclen, &inProcessed, dst, outSize,
\r
4380 +#ifndef __KERNEL__
\r
4382 + fprintf(stderr, "err %d\n", err);
\r
4387 +int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src,
\r
4388 + struct sized_buf *dst)
\r
4390 + int err, by_lzma = 0;
\r
4391 + if (un->un_lzma && is_lzma(*src->buf)) {
\r
4393 + un->un_cmbuf = src->buf;
\r
4394 + un->un_cmlen = src->sz;
\r
4395 + un->un_resbuf = dst->buf;
\r
4396 + un->un_reslen = dst->sz;
\r
4398 + /* this library is thread-safe */
\r
4399 + err = LzmaUncompress(un);
\r
4403 + err = zlib_inflateReset(&un->un_stream);
\r
4404 + if (unlikely(err != Z_OK))
\r
4406 + un->un_stream.next_in = src->buf;
\r
4407 + un->un_stream.avail_in = src->sz;
\r
4408 + un->un_stream.next_out = dst->buf;
\r
4409 + un->un_stream.avail_out = dst->sz;
\r
4410 + err = zlib_inflate(&un->un_stream, Z_FINISH);
\r
4411 + if (err == Z_STREAM_END)
\r
4416 +#ifdef __KERNEL__
\r
4417 + WARN_ON_ONCE(1);
\r
4419 + char a[64] = "ZLIB ";
\r
4421 + strcpy(a, "LZMA ");
\r
4422 +#ifdef _REENTRANT
\r
4423 + strerror_r(err, a + 5, sizeof(a) - 5);
\r
4425 + strncat(a, strerror(err), sizeof(a) - 5);
\r
4428 + strncat(a, zError(err), sizeof(a) - 5);
\r
4429 + fprintf(stderr, "%s: %.*s\n", __func__, sizeof(a), a);
\r
4435 +int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz)
\r
4440 + un->un_lzma = do_lzma;
\r
4441 + memset(un->un_a, 0, sizeof(un->un_a));
\r
4442 + un->un_a[SQUN_PROB].buf = un->un_prob;
\r
4443 + un->un_a[SQUN_PROB].sz = sizeof(un->un_prob);
\r
4445 + un->un_a[SQUN_RESULT].buf = kmalloc(res_sz, GFP_KERNEL);
\r
4446 + if (unlikely(!un->un_a[SQUN_RESULT].buf))
\r
4448 + un->un_a[SQUN_RESULT].sz = res_sz;
\r
4451 + un->un_stream.next_in = NULL;
\r
4452 + un->un_stream.avail_in = 0;
\r
4453 +#ifdef __KERNEL__
\r
4454 + un->un_stream.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
\r
4455 + if (unlikely(!un->un_stream.workspace))
\r
4458 + un->un_stream.opaque = NULL;
\r
4459 + un->un_stream.zalloc = Z_NULL;
\r
4460 + un->un_stream.zfree = Z_NULL;
\r
4462 + err = zlib_inflateInit(&un->un_stream);
\r
4463 + if (unlikely(err == Z_MEM_ERROR))
\r
4469 +void sqlzma_fin(struct sqlzma_un *un)
\r
4472 + for (i = 0; i < SQUN_LAST; i++)
\r
4473 + if (un->un_a[i].buf && un->un_a[i].buf != un->un_prob)
\r
4474 + kfree(un->un_a[i].buf);
\r
4475 + BUG_ON(zlib_inflateEnd(&un->un_stream) != Z_OK);
\r
4478 +#ifdef __KERNEL__
\r
4479 +EXPORT_SYMBOL(sqlzma_un);
\r
4480 +EXPORT_SYMBOL(sqlzma_init);
\r
4481 +EXPORT_SYMBOL(sqlzma_fin);
\r
4484 +static int __init sqlzma_init(void)
\r
4489 +static void __exit sqlzma_exit(void)
\r
4493 +module_init(sqlzma_init);
\r
4494 +module_exit(sqlzma_exit);
\r
4497 +MODULE_LICENSE("GPL");
\r
4498 +MODULE_AUTHOR("Junjiro Okajima <hooanon05 at yahoo dot co dot jp>");
\r
4499 +MODULE_VERSION("$Id: uncomp.c,v 1.30 2007/03/04 12:45:53 jro Exp $");
\r
4500 +MODULE_DESCRIPTION("LZMA uncompress for squashfs. "
\r
4501 + "Some functions for squashfs to support LZMA and "
\r
4502 + "a tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org.");
\r
4504 diff -urN linux-2.6.23/include/linux/squashfs_fs.h linux-2.6.23.sqlzma/include/linux/squashfs_fs.h
\r
4505 --- linux-2.6.23/include/linux/squashfs_fs.h 1969-12-31 19:00:00.000000000 -0500
\r
4506 +++ linux-2.6.23.sqlzma/include/linux/squashfs_fs.h 2007-10-14 10:24:31.000000000 -0400
\r
4508 +#ifndef SQUASHFS_FS
\r
4509 +#define SQUASHFS_FS
\r
4514 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
\r
4515 + * Phillip Lougher <phillip@lougher.org.uk>
\r
4517 + * This program is free software; you can redistribute it and/or
\r
4518 + * modify it under the terms of the GNU General Public License
\r
4519 + * as published by the Free Software Foundation; either version 2,
\r
4520 + * or (at your option) any later version.
\r
4522 + * This program is distributed in the hope that it will be useful,
\r
4523 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
4524 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
4525 + * GNU General Public License for more details.
\r
4527 + * You should have received a copy of the GNU General Public License
\r
4528 + * along with this program; if not, write to the Free Software
\r
4529 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
4534 +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
\r
4535 +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
\r
4538 +#ifdef CONFIG_SQUASHFS_VMALLOC
\r
4539 +#define SQUASHFS_ALLOC(a) vmalloc(a)
\r
4540 +#define SQUASHFS_FREE(a) vfree(a)
\r
4542 +#define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL)
\r
4543 +#define SQUASHFS_FREE(a) kfree(a)
\r
4545 +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
\r
4546 +#define SQUASHFS_MAJOR 3
\r
4547 +#define SQUASHFS_MINOR 0
\r
4548 +#define SQUASHFS_MAGIC 0x73717368
\r
4549 +#define SQUASHFS_MAGIC_SWAP 0x68737173
\r
4550 +#define SQUASHFS_START 0
\r
4552 +/* size of metadata (inode and directory) blocks */
\r
4553 +#define SQUASHFS_METADATA_SIZE 8192
\r
4554 +#define SQUASHFS_METADATA_LOG 13
\r
4556 +/* default size of data blocks */
\r
4557 +#define SQUASHFS_FILE_SIZE 65536
\r
4558 +#define SQUASHFS_FILE_LOG 16
\r
4560 +#define SQUASHFS_FILE_MAX_SIZE 65536
\r
4562 +/* Max number of uids and gids */
\r
4563 +#define SQUASHFS_UIDS 256
\r
4564 +#define SQUASHFS_GUIDS 255
\r
4566 +/* Max length of filename (not 255) */
\r
4567 +#define SQUASHFS_NAME_LEN 256
\r
4569 +#define SQUASHFS_INVALID ((long long) 0xffffffffffff)
\r
4570 +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff)
\r
4571 +#define SQUASHFS_INVALID_BLK ((long long) -1)
\r
4572 +#define SQUASHFS_USED_BLK ((long long) -2)
\r
4574 +/* Filesystem flags */
\r
4575 +#define SQUASHFS_NOI 0
\r
4576 +#define SQUASHFS_NOD 1
\r
4577 +#define SQUASHFS_CHECK 2
\r
4578 +#define SQUASHFS_NOF 3
\r
4579 +#define SQUASHFS_NO_FRAG 4
\r
4580 +#define SQUASHFS_ALWAYS_FRAG 5
\r
4581 +#define SQUASHFS_DUPLICATE 6
\r
4582 +#define SQUASHFS_EXPORT 7
\r
4584 +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
\r
4586 +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
\r
4589 +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
\r
4592 +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
\r
4595 +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
\r
4596 + SQUASHFS_NO_FRAG)
\r
4598 +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
\r
4599 + SQUASHFS_ALWAYS_FRAG)
\r
4601 +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
\r
4602 + SQUASHFS_DUPLICATE)
\r
4604 +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \
\r
4605 + SQUASHFS_EXPORT)
\r
4607 +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \
\r
4610 +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
\r
4611 + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \
\r
4612 + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
\r
4613 + (duplicate_checking << 6) | (exportable << 7))
\r
4615 +/* Max number of types and file types */
\r
4616 +#define SQUASHFS_DIR_TYPE 1
\r
4617 +#define SQUASHFS_FILE_TYPE 2
\r
4618 +#define SQUASHFS_SYMLINK_TYPE 3
\r
4619 +#define SQUASHFS_BLKDEV_TYPE 4
\r
4620 +#define SQUASHFS_CHRDEV_TYPE 5
\r
4621 +#define SQUASHFS_FIFO_TYPE 6
\r
4622 +#define SQUASHFS_SOCKET_TYPE 7
\r
4623 +#define SQUASHFS_LDIR_TYPE 8
\r
4624 +#define SQUASHFS_LREG_TYPE 9
\r
4626 +/* 1.0 filesystem type definitions */
\r
4627 +#define SQUASHFS_TYPES 5
\r
4628 +#define SQUASHFS_IPC_TYPE 0
\r
4630 +/* Flag whether block is compressed or uncompressed, bit is set if block is
\r
4631 + * uncompressed */
\r
4632 +#define SQUASHFS_COMPRESSED_BIT (1 << 15)
\r
4634 +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
\r
4635 + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
\r
4637 +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
\r
4639 +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
\r
4641 +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \
\r
4642 + ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
\r
4643 + ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
\r
4645 +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
\r
4648 + * Inode number ops. Inodes consist of a compressed block number, and an
\r
4649 + * uncompressed offset within that block
\r
4651 +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16))
\r
4653 +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff))
\r
4655 +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\
\r
4658 +/* Compute 32 bit VFS inode number from squashfs inode number */
\r
4659 +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \
\r
4660 + ((b) >> 2) + 1))
\r
4663 +/* Translate between VFS mode and squashfs mode */
\r
4664 +#define SQUASHFS_MODE(a) ((a) & 0xfff)
\r
4666 +/* fragment and fragment table defines */
\r
4667 +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry))
\r
4669 +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
\r
4670 + SQUASHFS_METADATA_SIZE)
\r
4672 +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
\r
4673 + SQUASHFS_METADATA_SIZE)
\r
4675 +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
\r
4676 + SQUASHFS_METADATA_SIZE - 1) / \
\r
4677 + SQUASHFS_METADATA_SIZE)
\r
4679 +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
\r
4680 + sizeof(long long))
\r
4682 +/* inode lookup table defines */
\r
4683 +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t))
\r
4685 +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \
\r
4686 + SQUASHFS_METADATA_SIZE)
\r
4688 +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \
\r
4689 + SQUASHFS_METADATA_SIZE)
\r
4691 +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \
\r
4692 + SQUASHFS_METADATA_SIZE - 1) / \
\r
4693 + SQUASHFS_METADATA_SIZE)
\r
4695 +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\
\r
4696 + sizeof(long long))
\r
4698 +/* cached data constants for filesystem */
\r
4699 +#define SQUASHFS_CACHED_BLKS 8
\r
4701 +#define SQUASHFS_MAX_FILE_SIZE_LOG 64
\r
4703 +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \
\r
4704 + (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
\r
4706 +#define SQUASHFS_MARKER_BYTE 0xff
\r
4708 +/* meta index cache */
\r
4709 +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
\r
4710 +#define SQUASHFS_META_ENTRIES 31
\r
4711 +#define SQUASHFS_META_NUMBER 8
\r
4712 +#define SQUASHFS_SLOTS 4
\r
4714 +struct meta_entry {
\r
4715 + long long data_block;
\r
4716 + unsigned int index_block;
\r
4717 + unsigned short offset;
\r
4718 + unsigned short pad;
\r
4721 +struct meta_index {
\r
4722 + unsigned int inode_number;
\r
4723 + unsigned int offset;
\r
4724 + unsigned short entries;
\r
4725 + unsigned short skip;
\r
4726 + unsigned short locked;
\r
4727 + unsigned short pad;
\r
4728 + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES];
\r
4733 + * definitions for structures on disk
\r
4736 +typedef long long squashfs_block_t;
\r
4737 +typedef long long squashfs_inode_t;
\r
4739 +struct squashfs_super_block {
\r
4740 + unsigned int s_magic;
\r
4741 + unsigned int inodes;
\r
4742 + unsigned int bytes_used_2;
\r
4743 + unsigned int uid_start_2;
\r
4744 + unsigned int guid_start_2;
\r
4745 + unsigned int inode_table_start_2;
\r
4746 + unsigned int directory_table_start_2;
\r
4747 + unsigned int s_major:16;
\r
4748 + unsigned int s_minor:16;
\r
4749 + unsigned int block_size_1:16;
\r
4750 + unsigned int block_log:16;
\r
4751 + unsigned int flags:8;
\r
4752 + unsigned int no_uids:8;
\r
4753 + unsigned int no_guids:8;
\r
4754 + unsigned int mkfs_time /* time of filesystem creation */;
\r
4755 + squashfs_inode_t root_inode;
\r
4756 + unsigned int block_size;
\r
4757 + unsigned int fragments;
\r
4758 + unsigned int fragment_table_start_2;
\r
4759 + long long bytes_used;
\r
4760 + long long uid_start;
\r
4761 + long long guid_start;
\r
4762 + long long inode_table_start;
\r
4763 + long long directory_table_start;
\r
4764 + long long fragment_table_start;
\r
4765 + long long lookup_table_start;
\r
4766 +} __attribute__ ((packed));
\r
4768 +struct squashfs_dir_index {
\r
4769 + unsigned int index;
\r
4770 + unsigned int start_block;
\r
4771 + unsigned char size;
\r
4772 + unsigned char name[0];
\r
4773 +} __attribute__ ((packed));
\r
4775 +#define SQUASHFS_BASE_INODE_HEADER \
\r
4776 + unsigned int inode_type:4; \
\r
4777 + unsigned int mode:12; \
\r
4778 + unsigned int uid:8; \
\r
4779 + unsigned int guid:8; \
\r
4780 + unsigned int mtime; \
\r
4781 + unsigned int inode_number;
\r
4783 +struct squashfs_base_inode_header {
\r
4784 + SQUASHFS_BASE_INODE_HEADER;
\r
4785 +} __attribute__ ((packed));
\r
4787 +struct squashfs_ipc_inode_header {
\r
4788 + SQUASHFS_BASE_INODE_HEADER;
\r
4789 + unsigned int nlink;
\r
4790 +} __attribute__ ((packed));
\r
4792 +struct squashfs_dev_inode_header {
\r
4793 + SQUASHFS_BASE_INODE_HEADER;
\r
4794 + unsigned int nlink;
\r
4795 + unsigned short rdev;
\r
4796 +} __attribute__ ((packed));
\r
4798 +struct squashfs_symlink_inode_header {
\r
4799 + SQUASHFS_BASE_INODE_HEADER;
\r
4800 + unsigned int nlink;
\r
4801 + unsigned short symlink_size;
\r
4802 + char symlink[0];
\r
4803 +} __attribute__ ((packed));
\r
4805 +struct squashfs_reg_inode_header {
\r
4806 + SQUASHFS_BASE_INODE_HEADER;
\r
4807 + squashfs_block_t start_block;
\r
4808 + unsigned int fragment;
\r
4809 + unsigned int offset;
\r
4810 + unsigned int file_size;
\r
4811 + unsigned short block_list[0];
\r
4812 +} __attribute__ ((packed));
\r
4814 +struct squashfs_lreg_inode_header {
\r
4815 + SQUASHFS_BASE_INODE_HEADER;
\r
4816 + unsigned int nlink;
\r
4817 + squashfs_block_t start_block;
\r
4818 + unsigned int fragment;
\r
4819 + unsigned int offset;
\r
4820 + long long file_size;
\r
4821 + unsigned short block_list[0];
\r
4822 +} __attribute__ ((packed));
\r
4824 +struct squashfs_dir_inode_header {
\r
4825 + SQUASHFS_BASE_INODE_HEADER;
\r
4826 + unsigned int nlink;
\r
4827 + unsigned int file_size:19;
\r
4828 + unsigned int offset:13;
\r
4829 + unsigned int start_block;
\r
4830 + unsigned int parent_inode;
\r
4831 +} __attribute__ ((packed));
\r
4833 +struct squashfs_ldir_inode_header {
\r
4834 + SQUASHFS_BASE_INODE_HEADER;
\r
4835 + unsigned int nlink;
\r
4836 + unsigned int file_size:27;
\r
4837 + unsigned int offset:13;
\r
4838 + unsigned int start_block;
\r
4839 + unsigned int i_count:16;
\r
4840 + unsigned int parent_inode;
\r
4841 + struct squashfs_dir_index index[0];
\r
4842 +} __attribute__ ((packed));
\r
4844 +union squashfs_inode_header {
\r
4845 + struct squashfs_base_inode_header base;
\r
4846 + struct squashfs_dev_inode_header dev;
\r
4847 + struct squashfs_symlink_inode_header symlink;
\r
4848 + struct squashfs_reg_inode_header reg;
\r
4849 + struct squashfs_lreg_inode_header lreg;
\r
4850 + struct squashfs_dir_inode_header dir;
\r
4851 + struct squashfs_ldir_inode_header ldir;
\r
4852 + struct squashfs_ipc_inode_header ipc;
\r
4855 +struct squashfs_dir_entry {
\r
4856 + unsigned int offset:13;
\r
4857 + unsigned int type:3;
\r
4858 + unsigned int size:8;
\r
4859 + int inode_number:16;
\r
4861 +} __attribute__ ((packed));
\r
4863 +struct squashfs_dir_header {
\r
4864 + unsigned int count:8;
\r
4865 + unsigned int start_block;
\r
4866 + unsigned int inode_number;
\r
4867 +} __attribute__ ((packed));
\r
4869 +struct squashfs_fragment_entry {
\r
4870 + long long start_block;
\r
4871 + unsigned int size;
\r
4872 + unsigned int pending;
\r
4873 +} __attribute__ ((packed));
\r
4875 +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
\r
4876 +extern int squashfs_uncompress_init(void);
\r
4877 +extern int squashfs_uncompress_exit(void);
\r
4880 + * macros to convert each packed bitfield structure from little endian to big
\r
4881 + * endian and vice versa. These are needed when creating or using a filesystem
\r
4882 + * on a machine with different byte ordering to the target architecture.
\r
4886 +#define SQUASHFS_SWAP_START \
\r
4889 + unsigned long long val;\
\r
4890 + unsigned char *s;\
\r
4891 + unsigned char *d;
\r
4893 +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
\r
4894 + SQUASHFS_SWAP_START\
\r
4895 + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
\r
4896 + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
\r
4897 + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
\r
4898 + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
\r
4899 + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
\r
4900 + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
\r
4901 + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
\r
4902 + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
\r
4903 + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
\r
4904 + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
\r
4905 + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
\r
4906 + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
\r
4907 + SQUASHFS_SWAP((s)->flags, d, 288, 8);\
\r
4908 + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
\r
4909 + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
\r
4910 + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
\r
4911 + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
\r
4912 + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
\r
4913 + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
\r
4914 + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
\r
4915 + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
\r
4916 + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
\r
4917 + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
\r
4918 + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
\r
4919 + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
\r
4920 + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
\r
4921 + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\
\r
4924 +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
\r
4925 + SQUASHFS_MEMSET(s, d, n);\
\r
4926 + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
\r
4927 + SQUASHFS_SWAP((s)->mode, d, 4, 12);\
\r
4928 + SQUASHFS_SWAP((s)->uid, d, 16, 8);\
\r
4929 + SQUASHFS_SWAP((s)->guid, d, 24, 8);\
\r
4930 + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
\r
4931 + SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
\r
4933 +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
\r
4934 + SQUASHFS_SWAP_START\
\r
4935 + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
\r
4938 +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
\r
4939 + SQUASHFS_SWAP_START\
\r
4940 + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
\r
4941 + sizeof(struct squashfs_ipc_inode_header))\
\r
4942 + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
\r
4945 +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
\r
4946 + SQUASHFS_SWAP_START\
\r
4947 + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
\r
4948 + sizeof(struct squashfs_dev_inode_header)); \
\r
4949 + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
\r
4950 + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
\r
4953 +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
\r
4954 + SQUASHFS_SWAP_START\
\r
4955 + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
\r
4956 + sizeof(struct squashfs_symlink_inode_header));\
\r
4957 + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
\r
4958 + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
\r
4961 +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
\r
4962 + SQUASHFS_SWAP_START\
\r
4963 + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
\r
4964 + sizeof(struct squashfs_reg_inode_header));\
\r
4965 + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
\r
4966 + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
\r
4967 + SQUASHFS_SWAP((s)->offset, d, 192, 32);\
\r
4968 + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
\r
4971 +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
\r
4972 + SQUASHFS_SWAP_START\
\r
4973 + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
\r
4974 + sizeof(struct squashfs_lreg_inode_header));\
\r
4975 + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
\r
4976 + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
\r
4977 + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
\r
4978 + SQUASHFS_SWAP((s)->offset, d, 224, 32);\
\r
4979 + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
\r
4982 +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
\r
4983 + SQUASHFS_SWAP_START\
\r
4984 + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
\r
4985 + sizeof(struct squashfs_dir_inode_header));\
\r
4986 + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
\r
4987 + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
\r
4988 + SQUASHFS_SWAP((s)->offset, d, 147, 13);\
\r
4989 + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
\r
4990 + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
\r
4993 +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
\r
4994 + SQUASHFS_SWAP_START\
\r
4995 + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
\r
4996 + sizeof(struct squashfs_ldir_inode_header));\
\r
4997 + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
\r
4998 + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
\r
4999 + SQUASHFS_SWAP((s)->offset, d, 155, 13);\
\r
5000 + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
\r
5001 + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
\r
5002 + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
\r
5005 +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
\r
5006 + SQUASHFS_SWAP_START\
\r
5007 + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
\r
5008 + SQUASHFS_SWAP((s)->index, d, 0, 32);\
\r
5009 + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
\r
5010 + SQUASHFS_SWAP((s)->size, d, 64, 8);\
\r
5013 +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
\r
5014 + SQUASHFS_SWAP_START\
\r
5015 + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
\r
5016 + SQUASHFS_SWAP((s)->count, d, 0, 8);\
\r
5017 + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
\r
5018 + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
\r
5021 +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
\r
5022 + SQUASHFS_SWAP_START\
\r
5023 + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
\r
5024 + SQUASHFS_SWAP((s)->offset, d, 0, 13);\
\r
5025 + SQUASHFS_SWAP((s)->type, d, 13, 3);\
\r
5026 + SQUASHFS_SWAP((s)->size, d, 16, 8);\
\r
5027 + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
\r
5030 +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
\r
5031 + SQUASHFS_SWAP_START\
\r
5032 + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
\r
5033 + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
\r
5034 + SQUASHFS_SWAP((s)->size, d, 64, 32);\
\r
5037 +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1)
\r
5039 +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
\r
5041 + int bit_position;\
\r
5042 + SQUASHFS_SWAP_START\
\r
5043 + SQUASHFS_MEMSET(s, d, n * 2);\
\r
5044 + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
\r
5046 + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
\r
5049 +#define SQUASHFS_SWAP_INTS(s, d, n) {\
\r
5051 + int bit_position;\
\r
5052 + SQUASHFS_SWAP_START\
\r
5053 + SQUASHFS_MEMSET(s, d, n * 4);\
\r
5054 + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
\r
5056 + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
\r
5059 +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
\r
5061 + int bit_position;\
\r
5062 + SQUASHFS_SWAP_START\
\r
5063 + SQUASHFS_MEMSET(s, d, n * 8);\
\r
5064 + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
\r
5066 + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
\r
5069 +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
\r
5071 + int bit_position;\
\r
5072 + SQUASHFS_SWAP_START\
\r
5073 + SQUASHFS_MEMSET(s, d, n * bits / 8);\
\r
5074 + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
\r
5076 + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
\r
5079 +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
\r
5080 +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
\r
5082 +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
\r
5084 +struct squashfs_base_inode_header_1 {
\r
5085 + unsigned int inode_type:4;
\r
5086 + unsigned int mode:12; /* protection */
\r
5087 + unsigned int uid:4; /* index into uid table */
\r
5088 + unsigned int guid:4; /* index into guid table */
\r
5089 +} __attribute__ ((packed));
\r
5091 +struct squashfs_ipc_inode_header_1 {
\r
5092 + unsigned int inode_type:4;
\r
5093 + unsigned int mode:12; /* protection */
\r
5094 + unsigned int uid:4; /* index into uid table */
\r
5095 + unsigned int guid:4; /* index into guid table */
\r
5096 + unsigned int type:4;
\r
5097 + unsigned int offset:4;
\r
5098 +} __attribute__ ((packed));
\r
5100 +struct squashfs_dev_inode_header_1 {
\r
5101 + unsigned int inode_type:4;
\r
5102 + unsigned int mode:12; /* protection */
\r
5103 + unsigned int uid:4; /* index into uid table */
\r
5104 + unsigned int guid:4; /* index into guid table */
\r
5105 + unsigned short rdev;
\r
5106 +} __attribute__ ((packed));
\r
5108 +struct squashfs_symlink_inode_header_1 {
\r
5109 + unsigned int inode_type:4;
\r
5110 + unsigned int mode:12; /* protection */
\r
5111 + unsigned int uid:4; /* index into uid table */
\r
5112 + unsigned int guid:4; /* index into guid table */
\r
5113 + unsigned short symlink_size;
\r
5114 + char symlink[0];
\r
5115 +} __attribute__ ((packed));
\r
5117 +struct squashfs_reg_inode_header_1 {
\r
5118 + unsigned int inode_type:4;
\r
5119 + unsigned int mode:12; /* protection */
\r
5120 + unsigned int uid:4; /* index into uid table */
\r
5121 + unsigned int guid:4; /* index into guid table */
\r
5122 + unsigned int mtime;
\r
5123 + unsigned int start_block;
\r
5124 + unsigned int file_size:32;
\r
5125 + unsigned short block_list[0];
\r
5126 +} __attribute__ ((packed));
\r
5128 +struct squashfs_dir_inode_header_1 {
\r
5129 + unsigned int inode_type:4;
\r
5130 + unsigned int mode:12; /* protection */
\r
5131 + unsigned int uid:4; /* index into uid table */
\r
5132 + unsigned int guid:4; /* index into guid table */
\r
5133 + unsigned int file_size:19;
\r
5134 + unsigned int offset:13;
\r
5135 + unsigned int mtime;
\r
5136 + unsigned int start_block:24;
\r
5137 +} __attribute__ ((packed));
\r
5139 +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
\r
5140 + SQUASHFS_MEMSET(s, d, n);\
\r
5141 + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
\r
5142 + SQUASHFS_SWAP((s)->mode, d, 4, 12);\
\r
5143 + SQUASHFS_SWAP((s)->uid, d, 16, 4);\
\r
5144 + SQUASHFS_SWAP((s)->guid, d, 20, 4);
\r
5146 +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
\r
5147 + SQUASHFS_SWAP_START\
\r
5148 + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
\r
5151 +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
\r
5152 + SQUASHFS_SWAP_START\
\r
5153 + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
\r
5154 + sizeof(struct squashfs_ipc_inode_header_1));\
\r
5155 + SQUASHFS_SWAP((s)->type, d, 24, 4);\
\r
5156 + SQUASHFS_SWAP((s)->offset, d, 28, 4);\
\r
5159 +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
\r
5160 + SQUASHFS_SWAP_START\
\r
5161 + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
\r
5162 + sizeof(struct squashfs_dev_inode_header_1));\
\r
5163 + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
\r
5166 +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
\r
5167 + SQUASHFS_SWAP_START\
\r
5168 + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
\r
5169 + sizeof(struct squashfs_symlink_inode_header_1));\
\r
5170 + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
\r
5173 +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
\r
5174 + SQUASHFS_SWAP_START\
\r
5175 + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
\r
5176 + sizeof(struct squashfs_reg_inode_header_1));\
\r
5177 + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
\r
5178 + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
\r
5179 + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
\r
5182 +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
\r
5183 + SQUASHFS_SWAP_START\
\r
5184 + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
\r
5185 + sizeof(struct squashfs_dir_inode_header_1));\
\r
5186 + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
\r
5187 + SQUASHFS_SWAP((s)->offset, d, 43, 13);\
\r
5188 + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
\r
5189 + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
\r
5194 +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
\r
5196 +struct squashfs_dir_index_2 {
\r
5197 + unsigned int index:27;
\r
5198 + unsigned int start_block:29;
\r
5199 + unsigned char size;
\r
5200 + unsigned char name[0];
\r
5201 +} __attribute__ ((packed));
\r
5203 +struct squashfs_base_inode_header_2 {
\r
5204 + unsigned int inode_type:4;
\r
5205 + unsigned int mode:12; /* protection */
\r
5206 + unsigned int uid:8; /* index into uid table */
\r
5207 + unsigned int guid:8; /* index into guid table */
\r
5208 +} __attribute__ ((packed));
\r
5210 +struct squashfs_ipc_inode_header_2 {
\r
5211 + unsigned int inode_type:4;
\r
5212 + unsigned int mode:12; /* protection */
\r
5213 + unsigned int uid:8; /* index into uid table */
\r
5214 + unsigned int guid:8; /* index into guid table */
\r
5215 +} __attribute__ ((packed));
\r
5217 +struct squashfs_dev_inode_header_2 {
\r
5218 + unsigned int inode_type:4;
\r
5219 + unsigned int mode:12; /* protection */
\r
5220 + unsigned int uid:8; /* index into uid table */
\r
5221 + unsigned int guid:8; /* index into guid table */
\r
5222 + unsigned short rdev;
\r
5223 +} __attribute__ ((packed));
\r
5225 +struct squashfs_symlink_inode_header_2 {
\r
5226 + unsigned int inode_type:4;
\r
5227 + unsigned int mode:12; /* protection */
\r
5228 + unsigned int uid:8; /* index into uid table */
\r
5229 + unsigned int guid:8; /* index into guid table */
\r
5230 + unsigned short symlink_size;
\r
5231 + char symlink[0];
\r
5232 +} __attribute__ ((packed));
\r
5234 +struct squashfs_reg_inode_header_2 {
\r
5235 + unsigned int inode_type:4;
\r
5236 + unsigned int mode:12; /* protection */
\r
5237 + unsigned int uid:8; /* index into uid table */
\r
5238 + unsigned int guid:8; /* index into guid table */
\r
5239 + unsigned int mtime;
\r
5240 + unsigned int start_block;
\r
5241 + unsigned int fragment;
\r
5242 + unsigned int offset;
\r
5243 + unsigned int file_size:32;
\r
5244 + unsigned short block_list[0];
\r
5245 +} __attribute__ ((packed));
\r
5247 +struct squashfs_dir_inode_header_2 {
\r
5248 + unsigned int inode_type:4;
\r
5249 + unsigned int mode:12; /* protection */
\r
5250 + unsigned int uid:8; /* index into uid table */
\r
5251 + unsigned int guid:8; /* index into guid table */
\r
5252 + unsigned int file_size:19;
\r
5253 + unsigned int offset:13;
\r
5254 + unsigned int mtime;
\r
5255 + unsigned int start_block:24;
\r
5256 +} __attribute__ ((packed));
\r
5258 +struct squashfs_ldir_inode_header_2 {
\r
5259 + unsigned int inode_type:4;
\r
5260 + unsigned int mode:12; /* protection */
\r
5261 + unsigned int uid:8; /* index into uid table */
\r
5262 + unsigned int guid:8; /* index into guid table */
\r
5263 + unsigned int file_size:27;
\r
5264 + unsigned int offset:13;
\r
5265 + unsigned int mtime;
\r
5266 + unsigned int start_block:24;
\r
5267 + unsigned int i_count:16;
\r
5268 + struct squashfs_dir_index_2 index[0];
\r
5269 +} __attribute__ ((packed));
\r
5271 +union squashfs_inode_header_2 {
\r
5272 + struct squashfs_base_inode_header_2 base;
\r
5273 + struct squashfs_dev_inode_header_2 dev;
\r
5274 + struct squashfs_symlink_inode_header_2 symlink;
\r
5275 + struct squashfs_reg_inode_header_2 reg;
\r
5276 + struct squashfs_dir_inode_header_2 dir;
\r
5277 + struct squashfs_ldir_inode_header_2 ldir;
\r
5278 + struct squashfs_ipc_inode_header_2 ipc;
\r
5281 +struct squashfs_dir_header_2 {
\r
5282 + unsigned int count:8;
\r
5283 + unsigned int start_block:24;
\r
5284 +} __attribute__ ((packed));
\r
5286 +struct squashfs_dir_entry_2 {
\r
5287 + unsigned int offset:13;
\r
5288 + unsigned int type:3;
\r
5289 + unsigned int size:8;
\r
5291 +} __attribute__ ((packed));
\r
5293 +struct squashfs_fragment_entry_2 {
\r
5294 + unsigned int start_block;
\r
5295 + unsigned int size;
\r
5296 +} __attribute__ ((packed));
\r
5298 +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
\r
5299 + SQUASHFS_MEMSET(s, d, n);\
\r
5300 + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
\r
5301 + SQUASHFS_SWAP((s)->mode, d, 4, 12);\
\r
5302 + SQUASHFS_SWAP((s)->uid, d, 16, 8);\
\r
5303 + SQUASHFS_SWAP((s)->guid, d, 24, 8);\
\r
5305 +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
\r
5306 + SQUASHFS_SWAP_START\
\r
5307 + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
\r
5310 +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
\r
5311 + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
\r
5313 +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
\r
5314 + SQUASHFS_SWAP_START\
\r
5315 + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
\r
5316 + sizeof(struct squashfs_dev_inode_header_2)); \
\r
5317 + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
\r
5320 +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
\r
5321 + SQUASHFS_SWAP_START\
\r
5322 + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
\r
5323 + sizeof(struct squashfs_symlink_inode_header_2));\
\r
5324 + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
\r
5327 +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
\r
5328 + SQUASHFS_SWAP_START\
\r
5329 + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
\r
5330 + sizeof(struct squashfs_reg_inode_header_2));\
\r
5331 + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
\r
5332 + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
\r
5333 + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
\r
5334 + SQUASHFS_SWAP((s)->offset, d, 128, 32);\
\r
5335 + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
\r
5338 +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
\r
5339 + SQUASHFS_SWAP_START\
\r
5340 + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
\r
5341 + sizeof(struct squashfs_dir_inode_header_2));\
\r
5342 + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
\r
5343 + SQUASHFS_SWAP((s)->offset, d, 51, 13);\
\r
5344 + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
\r
5345 + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
\r
5348 +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
\r
5349 + SQUASHFS_SWAP_START\
\r
5350 + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
\r
5351 + sizeof(struct squashfs_ldir_inode_header_2));\
\r
5352 + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
\r
5353 + SQUASHFS_SWAP((s)->offset, d, 59, 13);\
\r
5354 + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
\r
5355 + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
\r
5356 + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
\r
5359 +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
\r
5360 + SQUASHFS_SWAP_START\
\r
5361 + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
\r
5362 + SQUASHFS_SWAP((s)->index, d, 0, 27);\
\r
5363 + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
\r
5364 + SQUASHFS_SWAP((s)->size, d, 56, 8);\
\r
5366 +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
\r
5367 + SQUASHFS_SWAP_START\
\r
5368 + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
\r
5369 + SQUASHFS_SWAP((s)->count, d, 0, 8);\
\r
5370 + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
\r
5373 +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
\r
5374 + SQUASHFS_SWAP_START\
\r
5375 + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
\r
5376 + SQUASHFS_SWAP((s)->offset, d, 0, 13);\
\r
5377 + SQUASHFS_SWAP((s)->type, d, 13, 3);\
\r
5378 + SQUASHFS_SWAP((s)->size, d, 16, 8);\
\r
5381 +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
\r
5382 + SQUASHFS_SWAP_START\
\r
5383 + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
\r
5384 + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
\r
5385 + SQUASHFS_SWAP((s)->size, d, 32, 32);\
\r
5388 +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
\r
5390 +/* fragment and fragment table defines */
\r
5391 +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2))
\r
5393 +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \
\r
5394 + SQUASHFS_METADATA_SIZE)
\r
5396 +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \
\r
5397 + SQUASHFS_METADATA_SIZE)
\r
5399 +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \
\r
5400 + SQUASHFS_METADATA_SIZE - 1) / \
\r
5401 + SQUASHFS_METADATA_SIZE)
\r
5403 +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\
\r
5408 +#ifdef __KERNEL__
\r
5411 + * macros used to swap each structure entry, taking into account
\r
5412 + * bitfields and different bitfield placing conventions on differing
\r
5416 +#include <asm/byteorder.h>
\r
5418 +#ifdef __BIG_ENDIAN
\r
5419 + /* convert from little endian to big endian */
\r
5420 +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
\r
5423 + /* convert from big endian to little endian */
\r
5424 +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
\r
5425 + tbits, 64 - tbits - b_pos)
\r
5428 +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
\r
5429 + b_pos = pos % 8;\
\r
5431 + s = (unsigned char *)p + (pos / 8);\
\r
5432 + d = ((unsigned char *) &val) + 7;\
\r
5433 + for(bits = 0; bits < (tbits + b_pos); bits += 8) \
\r
5435 + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
\r
5438 +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n);
\r
5442 diff -urN linux-2.6.23/include/linux/squashfs_fs_i.h linux-2.6.23.sqlzma/include/linux/squashfs_fs_i.h
\r
5443 --- linux-2.6.23/include/linux/squashfs_fs_i.h 1969-12-31 19:00:00.000000000 -0500
\r
5444 +++ linux-2.6.23.sqlzma/include/linux/squashfs_fs_i.h 2007-10-14 10:24:31.000000000 -0400
\r
5446 +#ifndef SQUASHFS_FS_I
\r
5447 +#define SQUASHFS_FS_I
\r
5451 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
\r
5452 + * Phillip Lougher <phillip@lougher.org.uk>
\r
5454 + * This program is free software; you can redistribute it and/or
\r
5455 + * modify it under the terms of the GNU General Public License
\r
5456 + * as published by the Free Software Foundation; either version 2,
\r
5457 + * or (at your option) any later version.
\r
5459 + * This program is distributed in the hope that it will be useful,
\r
5460 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
5461 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
5462 + * GNU General Public License for more details.
\r
5464 + * You should have received a copy of the GNU General Public License
\r
5465 + * along with this program; if not, write to the Free Software
\r
5466 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
5468 + * squashfs_fs_i.h
\r
5471 +struct squashfs_inode_info {
\r
5472 + long long start_block;
\r
5473 + unsigned int offset;
\r
5476 + long long fragment_start_block;
\r
5477 + unsigned int fragment_size;
\r
5478 + unsigned int fragment_offset;
\r
5479 + long long block_list_start;
\r
5482 + long long directory_index_start;
\r
5483 + unsigned int directory_index_offset;
\r
5484 + unsigned int directory_index_count;
\r
5485 + unsigned int parent_inode;
\r
5488 + struct inode vfs_inode;
\r
5491 diff -urN linux-2.6.23/include/linux/squashfs_fs_sb.h linux-2.6.23.sqlzma/include/linux/squashfs_fs_sb.h
\r
5492 --- linux-2.6.23/include/linux/squashfs_fs_sb.h 1969-12-31 19:00:00.000000000 -0500
\r
5493 +++ linux-2.6.23.sqlzma/include/linux/squashfs_fs_sb.h 2007-10-14 14:32:50.000000000 -0400
\r
5495 +#ifndef SQUASHFS_FS_SB
\r
5496 +#define SQUASHFS_FS_SB
\r
5500 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
\r
5501 + * Phillip Lougher <phillip@lougher.org.uk>
\r
5503 + * This program is free software; you can redistribute it and/or
\r
5504 + * modify it under the terms of the GNU General Public License
\r
5505 + * as published by the Free Software Foundation; either version 2,
\r
5506 + * or (at your option) any later version.
\r
5508 + * This program is distributed in the hope that it will be useful,
\r
5509 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
5510 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
5511 + * GNU General Public License for more details.
\r
5513 + * You should have received a copy of the GNU General Public License
\r
5514 + * along with this program; if not, write to the Free Software
\r
5515 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
5517 + * squashfs_fs_sb.h
\r
5520 +#include <linux/squashfs_fs.h>
\r
5522 +struct squashfs_cache {
\r
5523 + long long block;
\r
5525 + long long next_index;
\r
5529 +struct squashfs_fragment_cache {
\r
5530 + long long block;
\r
5532 + unsigned int locked;
\r
5536 +struct squashfs_sb_info {
\r
5537 + struct squashfs_super_block sblk;
\r
5539 + int devblksize_log2;
\r
5541 + struct squashfs_cache *block_cache;
\r
5542 + struct squashfs_fragment_cache *fragment;
\r
5544 + int next_fragment;
\r
5545 + int next_meta_index;
\r
5546 + unsigned int *uid;
\r
5547 + unsigned int *guid;
\r
5548 + long long *fragment_index;
\r
5549 + unsigned int *fragment_index_2;
\r
5550 + char *read_page;
\r
5551 + //struct mutex read_data_mutex;
\r
5552 + struct mutex read_page_mutex;
\r
5553 + struct mutex block_cache_mutex;
\r
5554 + struct mutex fragment_mutex;
\r
5555 + struct mutex meta_index_mutex;
\r
5556 + wait_queue_head_t waitq;
\r
5557 + wait_queue_head_t fragment_wait_queue;
\r
5558 + struct meta_index *meta_index;
\r
5559 + long long *inode_lookup_table;
\r
5560 + int (*read_inode)(struct inode *i, squashfs_inode_t \
\r
5562 + long long (*read_blocklist)(struct inode *inode, int \
\r
5563 + index, int readahead_blks, char *block_list, \
\r
5564 + unsigned short **block_p, unsigned int *bsize);
\r
5565 + int (*read_fragment_index_table)(struct super_block *s);
\r
5568 diff -urN linux-2.6.23/init/do_mounts_rd.c linux-2.6.23.sqlzma/init/do_mounts_rd.c
\r
5569 --- linux-2.6.23/init/do_mounts_rd.c 2007-10-09 16:31:38.000000000 -0400
\r
5570 +++ linux-2.6.23.sqlzma/init/do_mounts_rd.c 2007-10-14 10:24:31.000000000 -0400
\r
5572 #include <linux/ext2_fs.h>
\r
5573 #include <linux/romfs_fs.h>
\r
5574 #include <linux/cramfs_fs.h>
\r
5575 +#include <linux/squashfs_fs.h>
\r
5576 #include <linux/initrd.h>
\r
5577 #include <linux/string.h>
\r
5580 * numbers could not be found.
\r
5582 * We currently check for the following magic numbers:
\r
5588 struct ext2_super_block *ext2sb;
\r
5589 struct romfs_super_block *romfsb;
\r
5590 struct cramfs_super *cramfsb;
\r
5591 + struct squashfs_super_block *squashfsb;
\r
5593 unsigned char *buf;
\r
5596 ext2sb = (struct ext2_super_block *) buf;
\r
5597 romfsb = (struct romfs_super_block *) buf;
\r
5598 cramfsb = (struct cramfs_super *) buf;
\r
5599 + squashfsb = (struct squashfs_super_block *) buf;
\r
5600 memset(buf, 0xe5, size);
\r
5603 @@ -101,6 +105,18 @@
\r
5607 + /* squashfs is at block zero too */
\r
5608 + if (squashfsb->s_magic == SQUASHFS_MAGIC) {
\r
5609 + printk(KERN_NOTICE
\r
5610 + "RAMDISK: squashfs filesystem found at block %d\n",
\r
5612 + if (squashfsb->s_major < 3)
\r
5613 + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
\r
5615 + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
\r
5620 * Read block 1 to test for minix and ext2 superblock
\r