[PATCH] Adds support for lzma payload. From: PLD Linux diff -p -up rpm-4.4.6/CHANGES.lzma rpm-4.4.6/CHANGES diff -p -up rpm-4.4.6/build/pack.c.lzma rpm-4.4.6/build/pack.c --- rpm-4.4.6/build/pack.c.lzma 2008-10-07 14:48:04.000000000 +0200 +++ rpm-4.4.6/build/pack.c 2008-10-07 14:48:05.000000000 +0200 @@ -587,6 +587,11 @@ int writeRPM(Header *hdrp, unsigned char /* Add prereq on rpm version that understands bzip2 payloads */ (void) rpmlibNeedsFeature(h, "PayloadIsBzip2", "3.0.5-1"); } + if (s[1] == 'l' && s[2] == 'z') { + (void) headerAddEntry(h, RPMTAG_PAYLOADCOMPRESSOR, RPM_STRING_TYPE, + "lzma", 1); + (void) rpmlibNeedsFeature(h, "PayloadIsLzma", "4.4.6-1"); + } strcpy(buf, rpmio_flags); buf[s - rpmio_flags] = '\0'; (void) headerAddEntry(h, RPMTAG_PAYLOADFLAGS, RPM_STRING_TYPE, buf+1, 1); diff -p -up rpm-4.4.6/lib/psm.c.lzma rpm-4.4.6/lib/psm.c --- rpm-4.4.6/lib/psm.c.lzma 2008-10-07 14:48:04.000000000 +0200 +++ rpm-4.4.6/lib/psm.c 2008-10-07 14:48:05.000000000 +0200 @@ -2157,6 +2157,8 @@ psm->te->h = headerFree(psm->te->h); t = stpcpy(t, ".gzdio"); if (!strcmp(payload_compressor, "bzip2")) t = stpcpy(t, ".bzdio"); + if (!strcmp(payload_compressor, "lzma")) + t = stpcpy(t, ".lzdio"); /*@-branchstate@*/ if (!hge(fi->h, RPMTAG_PAYLOADFORMAT, NULL, diff -p -up rpm-4.4.6/lib/rpmds.c.lzma rpm-4.4.6/lib/rpmds.c --- rpm-4.4.6/lib/rpmds.c.lzma 2006-04-07 00:06:14.000000000 +0200 +++ rpm-4.4.6/lib/rpmds.c 2008-10-07 14:48:23.000000000 +0200 @@ -1389,6 +1389,9 @@ static struct rpmlibProvides_s rpmlibPro { "rpmlib(PayloadIsUstar)", "4.4.4-1", (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), N_("package payload can be in ustar tar archive format.") }, + { "rpmlib(PayloadIsLzma)", "4.4.2-1", + (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), + N_("package payload can be compressed using lzma.") }, { NULL, NULL, 0, NULL } }; diff -p -up rpm-4.4.6/macros.in.lzma rpm-4.4.6/macros.in --- rpm-4.4.6/macros.in.lzma 2006-04-08 21:04:54.000000000 +0200 +++ rpm-4.4.6/macros.in 2008-10-07 14:48:05.000000000 +0200 @@ -324,6 +324,7 @@ package or when debugging this package.\ # Compression type and level for source/binary package payloads. # "w9.gzdio" gzip level 9 (default). # "w9.bzdio" bzip2 level 9. +# "w.lzdio" lzma # #%_source_payload w9.gzdio #%_binary_payload w9.gzdio diff -p -up rpm-4.4.6/rpm2cpio.c.lzma rpm-4.4.6/rpm2cpio.c --- rpm-4.4.6/rpm2cpio.c.lzma 2006-03-30 05:38:17.000000000 +0200 +++ rpm-4.4.6/rpm2cpio.c 2008-10-07 14:48:05.000000000 +0200 @@ -75,6 +75,8 @@ int main(int argc, char **argv) t = stpcpy(t, ".gzdio"); if (!strcmp(payload_compressor, "bzip2")) t = stpcpy(t, ".bzdio"); + if (!strcmp(payload_compressor, "lzma")) + t = stpcpy(t, ".lzdio"); } gzdi = Fdopen(fdi, rpmio_flags); /* XXX gzdi == fdi */ diff -p -up rpm-4.4.6/rpmio/LzmaDecode.c.lzma rpm-4.4.6/rpmio/LzmaDecode.c --- rpm-4.4.6/rpmio/LzmaDecode.c.lzma 2008-10-07 14:48:05.000000000 +0200 +++ rpm-4.4.6/rpmio/LzmaDecode.c 2008-10-07 14:48:05.000000000 +0200 @@ -0,0 +1,588 @@ +/* + LzmaDecode.c + LZMA Decoder (optimized for Speed version) + + LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this Code, expressly permits you to + statically or dynamically link your Code (or bind by name) to the + interfaces of this file without subjecting your linked Code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#include "LzmaDecode.h" + +#ifndef Byte +#define Byte unsigned char +#endif + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*Buffer++) + +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ + { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} + +#ifdef _LZMA_IN_CB + +#define RC_TEST { if (Buffer == BufferLim) \ + { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \ + BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }} + +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2 + +#else + +#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; } + +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 + +#endif + +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } + +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; + +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ + { UpdateBit0(p); mi <<= 1; A0; } else \ + { UpdateBit1(p); mi = (mi + mi) + 1; A1; } + +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) + +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ + { int i = numLevels; res = 1; \ + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \ + res -= (1 << numLevels); } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) +{ + unsigned char prop0; + if (size < LZMA_PROPERTIES_SIZE) + return LZMA_RESULT_DATA_ERROR; + prop0 = propsData[0]; + if (prop0 >= (9 * 5 * 5)) + return LZMA_RESULT_DATA_ERROR; + { + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); + propsRes->lc = prop0; + /* + unsigned char remainder = (unsigned char)(prop0 / 9); + propsRes->lc = prop0 % 9; + propsRes->pb = remainder / 5; + propsRes->lp = remainder % 5; + */ + } + + #ifdef _LZMA_OUT_READ + { + int i; + propsRes->DictionarySize = 0; + for (i = 0; i < 4; i++) + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8); + if (propsRes->DictionarySize == 0) + propsRes->DictionarySize = 1; + } + #endif + return LZMA_RESULT_OK; +} + +#define kLzmaStreamWasFinishedId (-1) + +int LzmaDecode(CLzmaDecoderState *vs, + #ifdef _LZMA_IN_CB + ILzmaInCallback *InCallback, + #else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + #endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) +{ + CProb *p = vs->Probs; + SizeT nowPos = 0; + Byte previousByte = 0; + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; + int lc = vs->Properties.lc; + + #ifdef _LZMA_OUT_READ + + UInt32 Range = vs->Range; + UInt32 Code = vs->Code; + #ifdef _LZMA_IN_CB + const Byte *Buffer = vs->Buffer; + const Byte *BufferLim = vs->BufferLim; + #else + const Byte *Buffer = inStream; + const Byte *BufferLim = inStream + inSize; + #endif + int state = vs->State; + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; + int len = vs->RemainLen; + UInt32 globalPos = vs->GlobalPos; + UInt32 distanceLimit = vs->DistanceLimit; + + Byte *dictionary = vs->Dictionary; + UInt32 dictionarySize = vs->Properties.DictionarySize; + UInt32 dictionaryPos = vs->DictionaryPos; + + Byte tempDictionary[4]; + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + if (len == kLzmaStreamWasFinishedId) + return LZMA_RESULT_OK; + + if (dictionarySize == 0) + { + dictionary = tempDictionary; + dictionarySize = 1; + tempDictionary[0] = vs->TempDictionary[0]; + } + + if (len == kLzmaNeedInitId) + { + { + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + UInt32 i; + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + rep0 = rep1 = rep2 = rep3 = 1; + state = 0; + globalPos = 0; + distanceLimit = 0; + dictionaryPos = 0; + dictionary[dictionarySize - 1] = 0; + #ifdef _LZMA_IN_CB + RC_INIT; + #else + RC_INIT(inStream, inSize); + #endif + } + len = 0; + } + while(len != 0 && nowPos < outSize) + { + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + len--; + } + if (dictionaryPos == 0) + previousByte = dictionary[dictionarySize - 1]; + else + previousByte = dictionary[dictionaryPos - 1]; + + #else /* if !_LZMA_OUT_READ */ + + int state = 0; + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; + int len = 0; + const Byte *Buffer; + const Byte *BufferLim; + UInt32 Range; + UInt32 Code; + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + + { + UInt32 i; + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + } + + #ifdef _LZMA_IN_CB + RC_INIT; + #else + RC_INIT(inStream, inSize); + #endif + + #endif /* _LZMA_OUT_READ */ + + while(nowPos < outSize) + { + CProb *prob; + UInt32 bound; + int posState = (int)( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & posStateMask); + + prob = p + IsMatch + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + int symbol = 1; + UpdateBit0(prob) + prob = p + Literal + (LZMA_LIT_SIZE * + ((( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & literalPosMask) << lc) + (previousByte >> (8 - lc)))); + + if (state >= kNumLitStates) + { + int matchByte; + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + matchByte = dictionary[pos]; + #else + matchByte = outStream[nowPos - rep0]; + #endif + do + { + int bit; + CProb *probLit; + matchByte <<= 1; + bit = (matchByte & 0x100); + probLit = prob + 0x100 + bit + symbol; + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) + } + while (symbol < 0x100); + } + while (symbol < 0x100) + { + CProb *probLit = prob + symbol; + RC_GET_BIT(probLit, symbol) + } + previousByte = (Byte)symbol; + + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #endif + if (state < 4) state = 0; + else if (state < 10) state -= 3; + else state -= 6; + } + else + { + UpdateBit1(prob); + prob = p + IsRep + state; + IfBit0(prob) + { + UpdateBit0(prob); + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + state = state < kNumLitStates ? 0 : 3; + prob = p + LenCoder; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG0 + state; + IfBit0(prob) + { + UpdateBit0(prob); + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + #ifdef _LZMA_OUT_READ + UInt32 pos; + #endif + UpdateBit0(prob); + + #ifdef _LZMA_OUT_READ + if (distanceLimit == 0) + #else + if (nowPos == 0) + #endif + return LZMA_RESULT_DATA_ERROR; + + state = state < kNumLitStates ? 9 : 11; + #ifdef _LZMA_OUT_READ + pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + #endif + + continue; + } + else + { + UpdateBit1(prob); + } + } + else + { + UInt32 distance; + UpdateBit1(prob); + prob = p + IsRepG1 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep1; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG2 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep2; + } + else + { + UpdateBit1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = p + RepLenCoder; + } + { + int numBits, offset; + CProb *probLen = prob + LenChoice; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + numBits = kLenNumLowBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenChoice2; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + numBits = kLenNumMidBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + numBits = kLenNumHighBits; + } + } + RangeDecoderBitTreeDecode(probLen, numBits, len); + len += offset; + } + + if (state < 4) + { + int posSlot; + state += kNumLitStates; + prob = p + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + rep0 = (2 | ((UInt32)posSlot & 1)); + if (posSlot < kEndPosModelIndex) + { + rep0 <<= numDirectBits; + prob = p + SpecPos + rep0 - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + RC_NORMALIZE + Range >>= 1; + rep0 <<= 1; + if (Code >= Range) + { + Code -= Range; + rep0 |= 1; + } + } + while (--numDirectBits != 0); + prob = p + Align; + rep0 <<= kNumAlignBits; + numDirectBits = kNumAlignBits; + } + { + int i = 1; + int mi = 1; + do + { + CProb *prob3 = prob + mi; + RC_GET_BIT2(prob3, mi, ; , rep0 |= i); + i <<= 1; + } + while(--numDirectBits != 0); + } + } + else + rep0 = posSlot; + if (++rep0 == (UInt32)(0)) + { + /* it's for stream version */ + len = kLzmaStreamWasFinishedId; + break; + } + } + + len += kMatchMinLen; + #ifdef _LZMA_OUT_READ + if (rep0 > distanceLimit) + #else + if (rep0 > nowPos) + #endif + return LZMA_RESULT_DATA_ERROR; + + #ifdef _LZMA_OUT_READ + if (dictionarySize - distanceLimit > (UInt32)len) + distanceLimit += len; + else + distanceLimit = dictionarySize; + #endif + + do + { + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + len--; + outStream[nowPos++] = previousByte; + } + while(len != 0 && nowPos < outSize); + } + } + RC_NORMALIZE; + + #ifdef _LZMA_OUT_READ + vs->Range = Range; + vs->Code = Code; + vs->DictionaryPos = dictionaryPos; + vs->GlobalPos = globalPos + (UInt32)nowPos; + vs->DistanceLimit = distanceLimit; + vs->Reps[0] = rep0; + vs->Reps[1] = rep1; + vs->Reps[2] = rep2; + vs->Reps[3] = rep3; + vs->State = state; + vs->RemainLen = len; + vs->TempDictionary[0] = tempDictionary[0]; + #endif + + #ifdef _LZMA_IN_CB + vs->Buffer = Buffer; + vs->BufferLim = BufferLim; + #else + *inSizeProcessed = (SizeT)(Buffer - inStream); + #endif + *outSizeProcessed = nowPos; + return LZMA_RESULT_OK; +} diff -p -up rpm-4.4.6/rpmio/LzmaDecode.h.lzma rpm-4.4.6/rpmio/LzmaDecode.h --- rpm-4.4.6/rpmio/LzmaDecode.h.lzma 2008-10-07 14:48:05.000000000 +0200 +++ rpm-4.4.6/rpmio/LzmaDecode.h 2008-10-07 14:48:05.000000000 +0200 @@ -0,0 +1,131 @@ +/* + LzmaDecode.h + LZMA Decoder interface + + LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this code, expressly permits you to + statically or dynamically link your code (or bind by name) to the + interfaces of this file without subjecting your linked code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#ifndef __LZMADECODE_H +#define __LZMADECODE_H + +#define _LZMA_IN_CB +/* Use callback for input data */ + +#define _LZMA_OUT_READ +/* Use read function for output data */ + +/* #define _LZMA_PROB32 */ +/* It can increase speed on some 32-bit CPUs, + but memory usage will be doubled in that case */ + +/* #define _LZMA_LOC_OPT */ +/* Enable local speed optimizations inside code */ + +/* #define _LZMA_SYSTEM_SIZE_T */ +/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/ + +#ifndef UInt32 +#ifdef _LZMA_UINT32_IS_ULONG +#define UInt32 unsigned long +#else +#define UInt32 unsigned int +#endif +#endif + +#ifndef SizeT +#ifdef _LZMA_SYSTEM_SIZE_T +#include <stddef.h> +#define SizeT size_t +#else +#define SizeT UInt32 +#endif +#endif + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb unsigned short +#endif + +#define LZMA_RESULT_OK 0 +#define LZMA_RESULT_DATA_ERROR 1 + +#ifdef _LZMA_IN_CB +typedef struct _ILzmaInCallback +{ + int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize); +} ILzmaInCallback; +#endif + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LZMA_PROPERTIES_SIZE 5 + +typedef struct _CLzmaProperties +{ + int lc; + int lp; + int pb; + #ifdef _LZMA_OUT_READ + UInt32 DictionarySize; + #endif +}CLzmaProperties; + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); + +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) + +#define kLzmaNeedInitId (-2) + +typedef struct _CLzmaDecoderState +{ + CLzmaProperties Properties; + CProb *Probs; + + #ifdef _LZMA_IN_CB + const unsigned char *Buffer; + const unsigned char *BufferLim; + #endif + + #ifdef _LZMA_OUT_READ + unsigned char *Dictionary; + UInt32 Range; + UInt32 Code; + UInt32 DictionaryPos; + UInt32 GlobalPos; + UInt32 DistanceLimit; + UInt32 Reps[4]; + int State; + int RemainLen; + unsigned char TempDictionary[4]; + #endif +} CLzmaDecoderState; + +#ifdef _LZMA_OUT_READ +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; } +#endif + +int LzmaDecode(CLzmaDecoderState *vs, + #ifdef _LZMA_IN_CB + ILzmaInCallback *inCallback, + #else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + #endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); + +#endif diff -p -up rpm-4.4.6/rpmio/Makefile.am.lzma rpm-4.4.6/rpmio/Makefile.am --- rpm-4.4.6/rpmio/Makefile.am.lzma 2006-04-01 12:30:16.000000000 +0200 +++ rpm-4.4.6/rpmio/Makefile.am 2008-10-07 14:48:29.000000000 +0200 @@ -22,7 +22,7 @@ pkginc_HEADERS = \ argv.h fts.h rmd128.h rmd160.h rpmdav.h \ rpmio.h rpmurl.h rpmmacro.h rpmlog.h rpmmessages.h rpmerr.h rpmpgp.h \ rpmsq.h rpmsw.h ugid.h -noinst_HEADERS = rpmio_internal.h rpmlua.h rpmhook.h +noinst_HEADERS = LzmaDecode.h rpmio_internal.h rpmlua.h rpmhook.h BEECRYPTLOBJS = $(shell test X"@WITH_BEECRYPT_SUBDIR@" != X && cat $(top_builddir)/@WITH_BEECTYPT_SUBDIR@/listobjs) @@ -34,7 +34,8 @@ librpmio_la_SOURCES = \ argv.c digest.c fts.c macro.c rmd128.c rmd160.c rpmdav.c \ rpmhook.c rpmio.c rpmlog.c rpmlua.c rpmmalloc.c \ rpmpgp.c rpmrpc.c rpmsq.c rpmsw.c strcasecmp.c strtolocale.c \ - stubs.c url.c ugid.c + stubs.c url.c ugid.c \ + LzmaDecode.c librpmio_la_LDFLAGS = -no-undefined -release $(LT_CURRENT).$(LT_REVISION) $(LDFLAGS) \ @WITH_BEECRYPT_LIB@ \ @WITH_NEON_LIB@ \ diff -p -up rpm-4.4.6/rpmio/librpmio.vers.lzma rpm-4.4.6/rpmio/librpmio.vers --- rpm-4.4.6/rpmio/librpmio.vers.lzma 2006-04-01 02:15:21.000000000 +0200 +++ rpm-4.4.6/rpmio/librpmio.vers 2008-10-07 14:48:05.000000000 +0200 @@ -85,6 +85,7 @@ LIBRPMIO_0 isCompressed; Link; Lstat; + lzdio; max_macro_depth; Mkdir; noLibio; diff -p -up rpm-4.4.6/rpmio/rpmio.c.lzma rpm-4.4.6/rpmio/rpmio.c --- rpm-4.4.6/rpmio/rpmio.c.lzma 2006-04-03 22:52:59.000000000 +0200 +++ rpm-4.4.6/rpmio/rpmio.c 2008-10-07 14:48:05.000000000 +0200 @@ -82,6 +82,7 @@ static int inet_aton(const char *cp, str #define FDONLY(fd) assert(fdGetIo(fd) == fdio) #define GZDONLY(fd) assert(fdGetIo(fd) == gzdio) #define BZDONLY(fd) assert(fdGetIo(fd) == bzdio) +#define LZDONLY(fd) assert(fdGetIo(fd) == lzdio) #define UFDONLY(fd) /* assert(fdGetIo(fd) == ufdio) */ @@ -182,6 +183,8 @@ static /*@observer@*/ const char * fdbg( } else if (fps->io == bzdio) { sprintf(be, "BZD %p fdno %d", fps->fp, fps->fdno); #endif + } else if (fps->io == lzdio) { + sprintf(be, "LZD %p fdno %d", fps->fp, fps->fdno); } else if (fps->io == fpio) { /*@+voidabstract@*/ sprintf(be, "%s %p(%d) fdno %d", @@ -2565,6 +2568,327 @@ FDIO_t bzdio = /*@-compmempass@*/ &bzdio /*@=moduncon@*/ #endif /* HAVE_BZLIB_H */ +#include "LzmaDecode.h" + +#define kInBufferSize (1 << 15) +typedef struct _CBuffer +{ + ILzmaInCallback InCallback; + FILE *File; + unsigned char Buffer[kInBufferSize]; +} CBuffer; + +typedef struct lzfile { + CBuffer g_InBuffer; + CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ + unsigned char properties[LZMA_PROPERTIES_SIZE]; + +// FILE *file; + int pid; +} LZFILE; + +static size_t MyReadFile(FILE *file, void *data, size_t size) +{ + if (size == 0) return 0; + return fread(data, 1, size, file); +} + +static int MyReadFileAndCheck(FILE *file, void *data, size_t size) +{ + return (MyReadFile(file, data, size) == size); +} + +static int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size) +{ + CBuffer *b = (CBuffer *)object; + *buffer = b->Buffer; + *size = (SizeT)MyReadFile(b->File, b->Buffer, kInBufferSize); + return LZMA_RESULT_OK; +} + +static inline /*@dependent@*/ void * lzdFileno(FD_t fd) + /*@*/ +{ + void * rc = NULL; + int i; + + FDSANE(fd); + for (i = fd->nfps; i >= 0; i--) { +/*@-boundsread@*/ + FDSTACK_t * fps = &fd->fps[i]; +/*@=boundsread@*/ + if (fps->io != lzdio) + continue; + rc = fps->fp; + break; + } + + return rc; +} + +static FD_t lzdWriteOpen(int fdno, int fopen) +{ + int pid; + int p[2]; + + if (fdno < 0) return NULL; + if (pipe(p) < 0) { + close(fdno); + return NULL; + } + pid = fork(); + if (pid < 0) { + close(fdno); + return NULL; + } + if (pid) { + FD_t fd; + LZFILE *lzfile; + + close(fdno); + close(p[0]); + lzfile = calloc(1, sizeof(*lzfile)); + if (lzfile == NULL) return NULL; + lzfile->g_InBuffer.File = fdopen(p[1], "wb"); + lzfile->pid = pid; + if (lzfile->g_InBuffer.File == NULL) { + close(p[1]); + free(lzfile); + return NULL; + } + fd = fdNew("open (lzdOpen write)"); + if (fopen) fdPop(fd); + fdPush(fd, lzdio, lzfile, -1); + return fdLink(fd, "lzdOpen"); + } else { + int i; + /* lzma */ + close(p[1]); + dup2(p[0], 0); + dup2(fdno, 1); + for (i = 3; i < 1024; i++) close(i); + if (execl("/usr/bin/lzma", "lzma", "e", "-si", "-so", NULL)) { + _exit(1); + } + } + return NULL; /* warning */ +} + +static FD_t lzdReadOpen(int fdno, int fopen) +{ + LZFILE *lzfile; + unsigned char ff[8]; + FD_t fd; + + if (fdno < 0) return NULL; + lzfile = calloc(1, sizeof(*lzfile)); + if (lzfile == NULL) return NULL; + lzfile->g_InBuffer.File = fdopen(fdno, "rb"); + if (lzfile->g_InBuffer.File == NULL) goto error2; + + if (!MyReadFileAndCheck(lzfile->g_InBuffer.File, lzfile->properties, sizeof(lzfile->properties))) { +error: + fclose(lzfile->g_InBuffer.File); +error2: + free(lzfile); + return NULL; + } + if (!MyReadFileAndCheck(lzfile->g_InBuffer.File, ff, 8)) goto error; + if (LzmaDecodeProperties(&lzfile->state.Properties, lzfile->properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) + goto error; + lzfile->state.Probs = (CProb *)malloc(LzmaGetNumProbs(&lzfile->state.Properties) * sizeof(CProb)); + if (lzfile->state.Probs == NULL) goto error; + + if (lzfile->state.Properties.DictionarySize == 0) + lzfile->state.Dictionary = 0; + else { + lzfile->state.Dictionary = (unsigned char *)malloc(lzfile->state.Properties.DictionarySize); + if (lzfile->state.Dictionary == NULL) { + free(lzfile->state.Probs); + goto error; + } + } + lzfile->g_InBuffer.InCallback.Read = LzmaReadCompressed; + LzmaDecoderInit(&lzfile->state); + + fd = fdNew("open (lzdOpen read)"); + if (fopen) fdPop(fd); + fdPush(fd, lzdio, lzfile, -1); + return fdLink(fd, "lzdOpen"); +} + +/*@-globuse@*/ +static /*@null@*/ FD_t lzdOpen(const char * path, const char * mode) + /*@globals fileSystem @*/ + /*@modifies fileSystem @*/ +{ + if (mode == NULL) + return NULL; + if (mode[0] == 'w') { + int fdno = open(path, O_WRONLY); + + if (fdno < 0) return NULL; + return lzdWriteOpen(fdno, 1); + } else { + int fdno = open(path, O_RDONLY); + + if (fdno < 0) return NULL; + return lzdReadOpen(fdno, 1); + } +} +/*@=globuse@*/ + +/*@-globuse@*/ +static /*@null@*/ FD_t lzdFdopen(void * cookie, const char * fmode) + /*@globals fileSystem, internalState @*/ + /*@modifies fileSystem, internalState @*/ +{ + FD_t fd = c2f(cookie); + int fdno; + + if (fmode == NULL) return NULL; + fdno = fdFileno(fd); + fdSetFdno(fd, -1); /* XXX skip the fdio close */ + if (fdno < 0) return NULL; + if (fmode[0] == 'w') { + return lzdWriteOpen(fdno, 0); + } else { + return lzdReadOpen(fdno, 0); + } +} +/*@=globuse@*/ + +/*@-globuse@*/ +static int lzdFlush(FD_t fd) + /*@globals fileSystem @*/ + /*@modifies fileSystem @*/ +{ + LZFILE *lzfile = lzdFileno(fd); + + if (lzfile == NULL || lzfile->g_InBuffer.File == NULL) return -2; + return fflush(lzfile->g_InBuffer.File); +} +/*@=globuse@*/ + +/* =============================================================== */ +/*@-globuse@*/ +/*@-mustmod@*/ /* LCL: *buf is modified */ +static ssize_t lzdRead(void * cookie, /*@out@*/ char * buf, size_t count) + /*@globals fileSystem, internalState @*/ + /*@modifies *buf, fileSystem, internalState @*/ +{ + FD_t fd = c2f(cookie); + LZFILE *lzfile; + ssize_t rc = 0; + int res = 0; + + if (fd->bytesRemain == 0) return 0; /* XXX simulate EOF */ + lzfile = lzdFileno(fd); + fdstat_enter(fd, FDSTAT_READ); + if (lzfile->g_InBuffer.File) + /*@-compdef@*/ + res = LzmaDecode(&lzfile->state, &lzfile->g_InBuffer.InCallback, buf, count, &rc); + /*@=compdef@*/ + if (res) { + if (lzfile) + fd->errcookie = "Lzma: decoding error"; + } else if (rc >= 0) { + fdstat_exit(fd, FDSTAT_READ, rc); + /*@-compdef@*/ + if (fd->ndigests && rc > 0) fdUpdateDigests(fd, (void *)buf, rc); + /*@=compdef@*/ + } + return rc; +} +/*@=mustmod@*/ +/*@=globuse@*/ + +/*@-globuse@*/ +static ssize_t lzdWrite(void * cookie, const char * buf, size_t count) + /*@globals fileSystem, internalState @*/ + /*@modifies fileSystem, internalState @*/ +{ + FD_t fd = c2f(cookie); + LZFILE *lzfile; + ssize_t rc; + + if (fd->bytesRemain == 0) return 0; /* XXX simulate EOF */ + + if (fd->ndigests && count > 0) fdUpdateDigests(fd, (void *)buf, count); + + lzfile = lzdFileno(fd); + fdstat_enter(fd, FDSTAT_WRITE); + rc = fwrite((void *)buf, 1, count, lzfile->g_InBuffer.File); + if (rc == -1) { + fd->errcookie = strerror(ferror(lzfile->g_InBuffer.File)); + } else if (rc > 0) { + fdstat_exit(fd, FDSTAT_WRITE, rc); + } + return rc; +} +/*@=globuse@*/ + +static inline int lzdSeek(void * cookie, /*@unused@*/ _libio_pos_t pos, + /*@unused@*/ int whence) + /*@*/ +{ + FD_t fd = c2f(cookie); + + LZDONLY(fd); + return -2; +} + +static int lzdClose( /*@only@*/ void * cookie) + /*@globals fileSystem, internalState @*/ + /*@modifies fileSystem, internalState @*/ +{ + FD_t fd = c2f(cookie); + LZFILE *lzfile; + int rc; + + lzfile = lzdFileno(fd); + + if (lzfile == NULL) return -2; + fdstat_enter(fd, FDSTAT_CLOSE); + /*@-noeffectuncon@*/ /* FIX: check rc */ + fclose(lzfile->g_InBuffer.File); + if (lzfile->pid) wait4(lzfile->pid, NULL, 0, NULL); + else { /* reading */ + free(lzfile->state.Probs); + if (lzfile->state.Dictionary) free(lzfile->state.Dictionary); + } + free(lzfile); + /*@=noeffectuncon@*/ + rc = 0; /* XXX FIXME */ + + /* XXX TODO: preserve fd if errors */ + + if (fd) { + if (rc == -1) { + fd->errcookie = strerror(ferror(lzfile->g_InBuffer.File)); + } else if (rc >= 0) { + fdstat_exit(fd, FDSTAT_CLOSE, rc); + } + } + +DBGIO(fd, (stderr, "==>\tlzdClose(%p) rc %lx %s\n", cookie, (unsigned long)rc, fdbg(fd))); + + if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "LZDIO", stderr); + /*@-branchstate@*/ + if (rc == 0) + fd = fdFree(fd, "open (lzdClose)"); + /*@=branchstate@*/ + return rc; +} + +/*@-type@*/ /* LCL: function typedefs */ +static struct FDIO_s lzdio_s = { + lzdRead, lzdWrite, lzdSeek, lzdClose, XfdLink, XfdFree, XfdNew, fdFileno, + NULL, lzdOpen, lzdFileno, lzdFlush, NULL, NULL, NULL, NULL, NULL +}; +/*@=type@*/ +FDIO_t lzdio = /*@-compmempass@*/ &lzdio_s /*@=compmempass@*/ ; + /* =============================================================== */ /*@observer@*/ static const char * getFdErrstr (FD_t fd) @@ -2583,7 +2907,9 @@ static const char * getFdErrstr (FD_t fd errstr = fd->errcookie; } else #endif /* HAVE_BZLIB_H */ - + if (fdGetIo(fd) == lzdio) { + errstr = fd->errcookie; + } else { errstr = (fd->syserrno ? strerror(fd->syserrno) : ""); } @@ -2903,6 +3229,9 @@ fprintf(stderr, "*** Fdopen(%p,%s) %s\n" fd = bzdFdopen(fd, zstdio); /*@=internalglobs@*/ #endif + } else if (!strcmp(end, "lzdio")) { + iof = lzdio; + fd = lzdFdopen(fd, zstdio); } else if (!strcmp(end, "ufdio")) { iof = ufdio; } else if (!strcmp(end, "fpio")) { @@ -3090,6 +3419,9 @@ int Ferror(FD_t fd) ec = (fd->syserrno || fd->errcookie != NULL) ? -1 : 0; i--; /* XXX fdio under bzdio always has fdno == -1 */ #endif + } else if (fps->io == lzdio) { + ec = (fd->syserrno || fd->errcookie != NULL) ? -1 : 0; + i--; /* XXX fdio under lzdio always has fdno == -1 */ } else { /* XXX need to check ufdio/gzdio/bzdio/fdio errors correctly. */ ec = (fdFileno(fd) < 0 ? -1 : 0); diff -p -up rpm-4.4.6/rpmio/rpmio.h.lzma rpm-4.4.6/rpmio/rpmio.h --- rpm-4.4.6/rpmio/rpmio.h.lzma 2005-11-04 00:19:54.000000000 +0100 +++ rpm-4.4.6/rpmio/rpmio.h 2008-10-07 14:48:05.000000000 +0200 @@ -673,6 +673,10 @@ int ufdGetFile( /*@killref@*/ FD_t sfd, /** */ +/*@observer@*/ /*@unchecked@*/ extern FDIO_t lzdio; + +/** + */ /*@observer@*/ /*@unchecked@*/ extern FDIO_t fadio; /*@=exportlocal@*/ /*@}*/